Repository navigation
release: 13.53.0 - #46958
release: 13.53.0#46958
Conversation
<!-- Please submit this PR as a draft initially. Do not mark it as "Ready for review" until the template has been completely filled out, and PR status checks have passed at least once. --> ## **Description** Stabilizes the flaky Multichain API E2E that adds an account from the edit connected accounts screen before the account list is ready. **Flake type:** Actions that Take Time **Root cause:** - The test opens the edit connected accounts screen and calls add new account. - The page-load check only waited for the header and the Save button. - The Add account control sits in the account list, which can appear after that check. - The test then waited 10 seconds for the Add account label and clicked once. - On a slow run that control was not in the page yet, so the wait timed out. The failure screenshot was taken after the timeout and already showed Add account **Solution:** - Wait for an account name row in `checkPageIsLoaded`, so the account list is on screen before the next step. - Wait up to 20 seconds until Add account stays visible for 1 second, then click it once. No retry-click and no fixed delay. Slack: https://consensys.slack.com/archives/CTQAGKY5V/p1790665207674129?thread_ts=1790584268.760419&cid=CTQAGKY5V ## **Changelog** CHANGELOG entry: null <!-- ## **Related issues** Fixes: --> ## **Manual testing steps** 1. Ensure a Flask test build is running (`yarn start:test:flask`). 2. Run: ```bash SELENIUM_BROWSER=chrome yarn test:e2e:single test/e2e/flask/multichain-api/evm/wallet_invokeMethod.spec.ts --debug --leave-running ``` 3. Confirm `Should match selected method to the expected output` passes (remove `it.only` before commit/PR). ## **Screenshots/Recordings** <img width="400" height="619" alt="image" src="https://github.com/user-attachments/assets/b39f8aad-c4c8-4c37-ada3-3c45615ffe91" /> ### **Before** Three CI failure screenshots from the same run: 1. Extension home: Account 1, banner "Still connecting to Localhost 8545... Update RPC", balance 25 ETH, Tokens tab, Network Localhost 8545. 2. Multichain test dapp: scopes eip155:1337, eip155:1338, eip155:1000 and two CAIP addresses added. Console error "Error creating session: Error: Request timeout". 3. MetaMask dialog "Select accounts": Wallet 1, Account 1 checked ($75,250.00), blue "Add account" with a plus icon, black Save button. This is the screen where the test timed out waiting for the add-account control. ### **After** No product UI change. The test waits for an account row on the edit-accounts screen, then waits until the Add account button stably shows "Add account", then clicks it once. <!-- ## **Pre-merge author checklist** - [ ] I've followed [MetaMask Contributor Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Extension Coding Standards](https://github.com/MetaMask/metamask-extension/blob/main/.github/guidelines/CODING_GUIDELINES.md). - [ ] I've completed the PR template to the best of my ability - [ ] I’ve included tests if applicable - [ ] I’ve documented my code using [JSDoc](https://jsdoc.app/) format if applicable - [ ] I’ve applied the right labels on the PR (see [labeling guidelines](https://github.com/MetaMask/metamask-extension/blob/main/.github/guidelines/LABELING_GUIDELINES.md)). Not required for external contributors. --> ## **Pre-merge reviewer checklist** - [ ] I've manually tested the PR (e.g. pull and build branch, run the app, test code being changed). - [ ] I confirm that this PR addresses all acceptance criteria described in the ticket it closes and includes the necessary testing evidence such as recordings and or screenshots. <!-- CURSOR_SUMMARY --> --- > [!NOTE] > **Low Risk** > E2e page-object timing only; no production or wallet logic changes. > > **Overview** > Fixes flaky Multichain API E2E when adding an account from the edit connected accounts screen by tightening **when** the test considers the UI ready and **how** it waits before clicking Add account. > > **`checkPageIsLoaded`** now also waits for at least one account name row (`anyAccountName`), not just the header and Save/Connect footer—so the account list (and the Add account control inside it) is on screen before **`addNewAccount`** runs. > > **`addNewAccount`** replaces a single 10s `waitForSelector` with a 20s `waitUntil` that requires the Add account button to stay present and visible for 1s (`stableFor`), then clicks once. > > <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit 097fce5. Bugbot is set up for automated code reviews on this repo. Configure [here](https://www.cursor.com/dashboard/bugbot).</sup> <!-- /CURSOR_SUMMARY --> --------- Co-authored-by: Cursor <cursoragent@cursor.com>
<!-- Please submit this PR as a draft initially. Do not mark it as "Ready for review" until the template has been completely filled out, and PR status checks have passed at least once. --> ## **Description** Stabilize the notifications enable E2E that times out while waiting for the Accounts list Add wallet button after identity onboarding. **Flake type:** Actions that Take Time **Root cause:** - The test finishes onboarding, then opens the Accounts list to add a second account. - Home only checks that account sync has succeeded at least once. That flag stays true even while a later sync is still running. - The Accounts screen still shows "Syncing..." and the Add wallet button stays disabled. - The test waits only 15 seconds for that button to stay enabled. Sync can take longer (the identity wait allows 45 seconds), so the wait times out. **Solution:** - After onboarding in this spec, wait until account-tree sync is idle before opening Accounts, so the menu is not opened while a sync is still running. - In the shared identity onboarding flow, wait until sync is idle after the "synced at least once" check, so callers leave Home only when sync has finished. - Raise the Accounts list sync wait from 15 seconds to 45 seconds so it matches the identity sync budget. SLack: https://consensys.slack.com/archives/CTQAGKY5V/p1790670778065499?thread_ts=1790670317.922329&cid=CTQAGKY5V <!-- ## **Related pull requests** --> ## **Changelog** CHANGELOG entry: null <!-- ## **Related issues** Fixes: --> ## **Manual testing steps** 1. Ensure a Chrome test build is available (`yarn start:test`). 2. Remove `it.only` from the failing test before committing or opening a PR. 3. Run: ```bash SELENIUM_BROWSER=chrome yarn test:e2e:single test/e2e/tests/notifications/enable-notifications.spec.ts --debug --leave-running ``` ## **Screenshots/Recordings** <img width="401" height="493" alt="image" src="https://github.com/user-attachments/assets/445f1e28-6ea8-4b69-96dd-bd2a5a703a9b" /> ### **Before** 1. Accounts screen at the timeout: header "Accounts", search field "Search your accounts", Account 1 with address 0xAa417...7405a, a spinner plus the text "Syncing...", and a gray disabled pill button also labeled "Syncing...". The Add wallet control is not enabled. 2. Earlier Home screen from the same run, before the Accounts list opened: "Fund your wallet", "Add funds", Buy / Swap / Send / Receive, tabs Tokens / Perps / DeFi / NFTs / Activity, same account address 0xAa417...7405a. ### **After** No product UI change. After onboarding, the test waits until account-tree sync is idle before opening Accounts, and the Accounts list sync wait is 45 seconds instead of 15. <!-- ## **Pre-merge author checklist** - [ ] I've followed [MetaMask Contributor Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Extension Coding Standards](https://github.com/MetaMask/metamask-extension/blob/main/.github/guidelines/CODING_GUIDELINES.md). - [ ] I've completed the PR template to the best of my ability - [ ] I've included tests if applicable - [ ] I've documented my code using [JSDoc](https://jsdoc.app/) format if applicable - [ ] I've applied the right labels on the PR (see [labeling guidelines](https://github.com/MetaMask/metamask-extension/blob/main/.github/guidelines/LABELING_GUIDELINES.md)). Not required for external contributors. --> ## **Pre-merge reviewer checklist** - [ ] I've manually tested the PR (e.g. pull and build branch, run the app, test code being changed). - [ ] I confirm that this PR addresses all acceptance criteria described in the ticket it closes and includes the necessary testing evidence such as recordings and or screenshots. <!-- CURSOR_SUMMARY --> --- > [!NOTE] > **Low Risk** > Test and page-object timing only; no production wallet or notification behavior changes. > > **Overview** > Fixes flaky **enable notifications** E2E timeouts when the Accounts list still shows **Syncing...** and keeps **Add wallet** disabled after identity onboarding. > > After onboarding, tests now call **`waitUntilAccountTreeSyncIdle`** so navigation to Accounts happens only when account-tree sync is finished—not merely after “synced at least once,” which can stay true while a later sync runs. That wait is wired into **`completeOnboardFlowIdentity`** and again in the notifications spec’s **`onboardAndAddAccount`** helper before opening the account menu. > > **`AccountListPage`** defaults for **`waitForAddWalletButtonStablyReady`** and **`waitUntilSyncingIsCompleted`** move from **15s** to **`BASE_ACCOUNT_SYNC_TIMEOUT` (45s)**, aligned with the identity sync budget. > > <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit 5564a87. Bugbot is set up for automated code reviews on this repo. Configure [here](https://www.cursor.com/dashboard/bugbot).</sup> <!-- /CURSOR_SUMMARY --> Co-authored-by: Cursor <cursoragent@cursor.com>
## **Description** Adds `continue-on-error: true` to every AWS OIDC job, so we can at least see builds and tests while this is being repaired. Adds an explicit "Temporary OIDC workaround always fail" ## **Changelog** CHANGELOG entry: null <!--## **Related issues** ## **Manual testing steps** ## **Screenshots/Recordings** ## **Pre-merge author checklist** ## **Pre-merge reviewer checklist**--> <!-- CURSOR_SUMMARY --> --- > [!NOTE] > **High Risk** > The CI status gate is forced to fail on every run, which blocks merge until reverted; S3 uploads and prerelease PR comments may fail silently while OIDC is down. > > **Overview** > **Temporary CI relief while AWS OIDC is broken:** artifact uploads and related token steps no longer fail the jobs that produce builds, tests, and benchmarks. > > `continue-on-error: true` is added on every `upload-s3` step touched in this PR (Storybook, TS migration dashboard, main bundle-size, prerelease test plan, audit baseline, benchmark matrices, and build/bundle-analyzer uploads in `run-build.yml`). Prerelease publishing also applies it to the `get-token` step used for PR build announcements, so a token exchange failure skips the announce step instead of killing the job. > > **Separately**, `ci-status-gate.yml` gains a first step **"Temporary OIDC workaround always fail"** that runs `exit 1`, so the aggregate **CI status gate** job fails immediately on every run (before the usual “all jobs passed” logic). That keeps the required gate red until this workaround is removed, even when builds and tests are green. > > <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit 4796788. Bugbot is set up for automated code reviews on this repo. Configure [here](https://www.cursor.com/dashboard/bugbot).</sup> <!-- /CURSOR_SUMMARY -->
…46925) ## **Description** Reverts #46881, now that AWS OIDC is working again ## **Changelog** CHANGELOG entry: null ## **Related issues** N/A ## **Manual testing steps** N/A ## **Screenshots/Recordings** N/A ## **Pre-merge author checklist** - [x] I've followed [MetaMask Contributor Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Extension Coding Standards](https://github.com/MetaMask/metamask-extension/blob/main/.github/guidelines/CODING_GUIDELINES.md). - [x] I've completed the PR template to the best of my ability - [x] I’ve included tests if applicable - [x] I’ve documented my code using [JSDoc](https://jsdoc.app/) format if applicable - [x] I’ve applied the right labels on the PR (see [labeling guidelines](https://github.com/MetaMask/metamask-extension/blob/main/.github/guidelines/LABELING_GUIDELINES.md)). Not required for external contributors. ## **Pre-merge reviewer checklist** - [ ] I've manually tested the PR (e.g. pull and build branch, run the app, test code being changed). - [ ] I confirm that this PR addresses all acceptance criteria described in the ticket it closes and includes the necessary testing evidence such as recordings and or screenshots.
## **Description** Follow-up to #46530 and [the shared host-check review comment](#46530 (comment)). The browser request filter and trusted-content deep-link resolver previously accepted subdomains of configured deep-link hosts. This PR limits both to the exact configured hosts (`link.metamask.io` and `link.metamask.com` by default). Subdomain URLs are no longer intercepted by the router or resolved as internal routes from trusted content; they remain external URLs and do not enter the extension's deep-link interstitial flow. Supported links on the configured hosts retain the existing interstitial policy. Move the host predicate and constants into `common.ts`, and reuse the exact-host check for home QR deep-link actions while retaining their HTTPS, default-port, and pathname requirements. Update router, helper, carousel, and home-action tests for the exact-host policy. ## **Changelog** CHANGELOG entry: Restricted deep-link handling to configured hosts instead of their subdomains. <!-- ## **Related issues** No separate issue; stacked on #46530. --> ## **Manual testing steps** 1. Build and load the extension from this branch. 2. Open an unsigned supported deep link on `https://link.metamask.io` and `https://link.metamask.com` in a new tab; verify each opens the security interstitial. 3. Open the same path on `https://invalid.link.metamask.io` or `https://invalid.link.metamask.com`; verify the extension does not intercept the navigation or open its interstitial. The destination site may show an error if the subdomain does not exist. 4. Open the home route with a `predictDeeplinkUrl` pointing to `https://link.metamask.com/predict`; verify the QR action appears. Repeat with `https://invalid.link.metamask.com/predict` or `https://link.metamask.com:444/predict` and verify it does not appear. 5. Click a trusted-content carousel slide linking to a supported route on an exact configured host and verify internal navigation; repeat with an invalid subdomain and verify it opens as an external URL. <!-- ## **Screenshots/Recordings** ### **Before** ### **After** No visual layout change. --> ## **Pre-merge author checklist** - [x] I followed MetaMask coding standards and completed the PR template. - [x] I included tests for the host checks and affected UI flows. - [ ] I applied the appropriate labels, if needed. <!-- ## **Pre-merge reviewer checklist** - [ ] Manually tested and confirmed acceptance criteria. --> <!-- CURSOR_SUMMARY --> --- > [!NOTE] > **High Risk** > This tightens a security boundary across interception, interstitial bypass, and QR deeplink acceptance; misconfiguration could break legitimate links, while the change reduces subdomain takeover/phishing risk. > > **Overview** > Deep-link interception and trusted-content resolution no longer treat **subdomains** of `link.metamask.io` / `link.metamask.com` as MetaMask links. Only those exact hostnames are handled; URLs like `https://invalid.link.metamask.io/...` stay normal external navigations (no extension router, no interstitial, no in-app route rewrite). > > The background **`webRequest`** filter changes from `*://*.${host}/*` to `*://${host}/*`, and **`isDeepLinkHost`** switches from suffix/subdomain matching to an exact list membership check. Shared symbols move from **`constants`** to **`common`**, and home QR deeplink validation reuses **`isDeepLinkHost`** with **HTTPS on the default port** plus pathname checks. > > <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit 0571886. Bugbot is set up for automated code reviews on this repo. Configure [here](https://www.cursor.com/dashboard/bugbot).</sup> <!-- /CURSOR_SUMMARY -->
## **Description** Deep links on `link.metamask.com` can be signed for their own origin. Keep verification of legacy `.io` signatures first, then try other configured signing hosts only for exact, configured HTTPS deep-link hosts. Preserve the canonical path and signed query while swapping the signing origin. Includes tests for `.io`, `.com`, lookalike hosts, HTTP/port restrictions, and signed query parameters. Stacked on #46748. Security team authorization was confirmed by the requester in the working conversation for this change. ## **Changelog** CHANGELOG entry: Fixed signature verification for deep links signed with configured MetaMask domains. <!-- ## **Related issues** Fixes: --> ## **Manual testing steps** 1. Load the extension from a test build and open a signed `link.metamask.com` deep link whose signature was generated for `link.metamask.com`; verify it resolves to the intended route. 2. Open an existing `.io`-signed deep link on both `link.metamask.io` and `link.metamask.com`; verify both continue to resolve. 3. Open invalid or unsigned links from an untrusted origin; verify the security interstitial still appears. 4. Open a link on a lookalike hostname or an HTTP URL; verify it is not accepted as an alternate signed-host link. <!-- ## **Screenshots/Recordings** ### **Before** ### **After** --> ## **Pre-merge author checklist** - [x] I've followed the MetaMask Contributor Docs and MetaMask Extension Coding Standards. - [x] I've completed the PR template to the best of my ability. - [x] I've included tests if applicable. - [ ] I've documented my code using JSDoc if applicable. - [ ] I've applied the right labels on the PR, if applicable. ## **Pre-merge reviewer checklist** - [ ] I've manually tested the PR. - [ ] I confirm that this PR addresses all acceptance criteria and includes the necessary testing evidence.
## Version Bump After Release This PR bumps the main branch version from 13.52.0 to 13.53.0 after cutting the release branch. ### Why this is needed: - **Nightly builds**: Each nightly build needs to be one minor version ahead of the current release candidate - **Version conflicts**: Prevents conflicts between nightlies and release candidates - **Platform alignment**: Maintains version alignment between MetaMask mobile and extension - **Update systems**: Ensures nightlies are accepted by app stores and browser update systems ### What changed: - Version bumped from `13.52.0` to `13.53.0` - Platform: `extension` - Files updated by `set-semvar-version.sh` script ### Next steps: This PR should be **manually reviewed and merged by the release manager** to maintain proper version flow. ### Related: - Release version: 13.52.0 - Release branch: release/13.52.0 - Platform: extension - Test mode: false --- *This PR was automatically created by the `create-platform-release-pr.sh` script.* Co-authored-by: metamaskbot <metamaskbot@users.noreply.github.com>
<!-- CURSOR_AGENT_PR_BODY_BEGIN -->
## **Description**
Several E2E page objects and shared helpers used fragile locators that
matched generic HTML tags (`button`, `p`, `h1`, `h2`, `div`) combined
with visible text. These selectors are brittle because unrelated
elements with the same tag and text can appear elsewhere in the DOM, and
they do not follow the project's preference for `data-testid`-based
locators.
This PR replaces those generic tag selectors with stable `data-testid`
locators that already exist in the UI.
**Problem areas addressed:**
- Homepage primary CTAs (Buy, Send, Receive, Swap) used `{ css:
'button', text: '...' }`
- Global menu Snaps entry used `{ text: 'Snaps', tag: 'div' }`
- Confirmation flows used `{ css: 'p' }` / `{ css: 'h2' }` for gas
details, titles, and transaction detail rows
- Account/details modals used generic `button` + text selectors where
test IDs exist
- Critical error and change-password warning pages used generic
heading/paragraph selectors
**Solution:**
- Use suffix-matching test IDs for EVM/non-EVM homepage buttons (e.g.
`[data-testid$="-overview-send"]`)
- Use confirmation-specific test IDs (`confirm-title-text`,
`transaction-details-recipient-row`, `edit-gas-fees-row`, etc.)
- Use modal/component test IDs for account details, address modal, and
password warning flows
- Handle Receive on non-EVM homepages by opening the More menu when
Receive is not on the primary action row
**Merge with main:**
- Merged latest `main` and resolved modify/delete conflict by accepting
removal of `dialog/account-details-modal.ts` (account details flows now
live in `accounts/details-page.ts` with existing test IDs).
## **Changelog**
CHANGELOG entry: null
## **Related issues**
Fixes:
## **Manual testing steps**
1. Run the extension test build (already in watch mode locally).
2. Run a subset of affected E2E specs to verify selectors resolve
correctly:
- `yarn test:e2e:single test/e2e/tests/btc/account-derivation.spec.ts
--browser=chrome`
- `yarn test:e2e:single test/e2e/tests/tron/account-derivation.spec.ts
--browser=chrome`
- `yarn test:e2e:single
test/e2e/tests/confirmations/transactions/erc20-approve.spec.ts
--browser=chrome`
- `yarn test:e2e:single test/e2e/tests/send/send-eth.spec.js
--browser=chrome`
3. Confirm homepage Send/Swap/Receive/Buy buttons are found and
clickable in any home-flow test.
4. Confirm transaction confirmation advanced gas details assertions pass
after toggling advanced details.
<!--
## **Screenshots/Recordings**
### **Before**
### **After**
-->
## **Pre-merge author checklist**
- [x] I've followed [MetaMask Contributor
Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask
Extension Coding
Standards](https://github.com/MetaMask/metamask-extension/blob/main/.github/guidelines/CODING_GUIDELINES.md).
- [x] I've completed the PR template to the best of my ability
- [ ] I've included tests if applicable
- [ ] I've documented my code using [JSDoc](https://jsdoc.app/) format
if applicable
- [ ] I've applied the right labels on the PR (see [labeling
guidelines](https://github.com/MetaMask/metamask-extension/blob/main/.github/guidelines/LABELING_GUIDELINES.md)).
Not required for external contributors.
## **Pre-merge reviewer checklist**
- [ ] I've manually tested the PR (e.g. pull and build branch, run the
app, test code being changed).
- [ ] I confirm that this PR addresses all acceptance criteria described
in the ticket it closes and includes the necessary testing evidence such
as recordings and or screenshots.
<!-- CURSOR_AGENT_PR_BODY_END -->
<div><a
href="https://cursor.com/agents/bc-a4329bc2-a68a-41f3-99d5-06d190fa3698?cursor_ref=pr_footer&cursor_cta=open_in_web"><picture><source
media="(prefers-color-scheme: dark)"
srcset="https://cursor.com/assets/images/open-in-web-dark.png"><source
media="(prefers-color-scheme: light)"
srcset="https://cursor.com/assets/images/open-in-web-light.png"><img
alt="Open in Web" width="114" height="28"
src="https://cursor.com/assets/images/open-in-web-dark.png"></picture></a> <a
href="https://cursor.com/background-agent?bcId=bc-a4329bc2-a68a-41f3-99d5-06d190fa3698&cursor_ref=pr_footer&cursor_cta=open_in_cursor"><picture><source
media="(prefers-color-scheme: dark)"
srcset="https://cursor.com/assets/images/open-in-cursor-dark.png"><source
media="(prefers-color-scheme: light)"
srcset="https://cursor.com/assets/images/open-in-cursor-light.png"><img
alt="Open in Cursor" width="131" height="28"
src="https://cursor.com/assets/images/open-in-cursor-dark.png"></picture></a> </div>
---------
Co-authored-by: Cursor Agent <cursoragent@cursor.com>
<!-- Please submit this PR as a draft initially. Do not mark it as "Ready for review" until the template has been completely filled out, and PR status checks have passed at least once. --> ## **Description** The add-network confirmation screen showed RPC URLs with Unicode homograph hostnames and did not warn when the chain was not on the safe list. Wire existing `isValidASCIIURL` / `toPunycodeURL` helpers: show the punycode host in the RPC row and emit `networkUrlErrorWarning` on that row before safe-chain validation. ## **Changelog** CHANGELOG entry: fix: add-network confirmations so homograph RPC hostnames show a warning ## **Related issues** Fixes: MetaMask/MetaMask-planning#7612 ## **Manual testing steps** 1. Load the extension and connect a test dapp. 2. Call `wallet_addEthereumChain` with an RPC URL whose hostname uses confusable Unicode (e.g. `https://iոfura.io/v3/...` with Armenian `ո` instead of ASCII `n`). 3. On the add-network confirmation, confirm the RPC row shows `xn--ifura-dig.io` (not the spoofed Unicode) and a warning on the RPC row with the punycode URL. 4. Repeat with a normal ASCII RPC URL and confirm there is no homograph warning. ## **Screenshots/Recordings** ### **Before** Homograph RPC hostname shown as-is; no RPC-row warning for unrecognized chains. ### **After** Punycode hostname in the RPC row; RPC-row warning with punycode version. ## **Pre-merge author checklist** - [ ] I've followed [MetaMask Contributor Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Extension Coding Standards](https://github.com/MetaMask/metamask-extension/blob/main/.github/guidelines/CODING_GUIDELINES.md). - [ ] I've completed the PR template to the best of my ability - [ ] I’ve included tests if applicable - [ ] I’ve documented my code using [JSDoc](https://jsdoc.app/) format if applicable - [ ] I’ve applied the right labels on the PR (see [labeling guidelines](https://github.com/MetaMask/metamask-extension/blob/main/.github/guidelines/LABELING_GUIDELINES.md)). Not required for external contributors. ## **Pre-merge reviewer checklist** - [ ] I've manually tested the PR (e.g. pull and build branch, run the app, test code being changed). - [ ] I confirm that this PR addresses all acceptance criteria described in the ticket it closes and includes the necessary testing evidence such as recordings and or screenshots. <!-- CURSOR_SUMMARY --> --- > [!NOTE] > **Medium Risk** > Changes add-network confirmation security UX (RPC display and warnings) where users decide which endpoint to trust; logic mirrors existing helpers used in the legacy template. > > **Overview** > **Add-network confirmations** now treat IDN homograph RPC hostnames like the legacy template: the RPC row shows the **punycode** hostname (not confusable Unicode), and a **warning** is raised on that row via `networkUrlErrorWarning` even when the chain is not on the safe list. > > `useAddEthereumChainAlerts` runs `isValidASCIIURL` on `requestData.rpcUrl` before safe-chain checks and emits `rpcUrlIdnHomograph` on the RPC field. Tests cover punycode display and the homograph alert. > > `networks-page.test.tsx` only stabilizes Chainlist/search tests by using `fireEvent.change` plus `waitFor` instead of `userEvent.type`. > > <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit 30e4c21. Bugbot is set up for automated code reviews on this repo. Configure [here](https://www.cursor.com/dashboard/bugbot).</sup> <!-- /CURSOR_SUMMARY --> --------- Co-authored-by: Cursor <cursoragent@cursor.com>
<!-- Please submit this PR as a draft initially. Do not mark it as "Ready for review" until the template has been completely filled out, and PR status checks have passed at least once. --> ## **Description** There's an intermittent issue where the snap simple keyring crashes, thus making the tests flaky. We change the specs to tolerate failure mode, until the issue is fully resolved/investigated. We'll work on supporting more debug logs a a separate task Bug ticket: #44026 Slack context: https://consensys.slack.com/archives/CTQAGKY5V/p1790584268760419 ## **Changelog** <!-- If this PR is not End-User-Facing and should not show up in the CHANGELOG, you can choose to either: 1. Write `CHANGELOG entry: null` 2. Label with `no-changelog` If this PR is End-User-Facing, please write a short User-Facing description in the past tense like: `CHANGELOG entry: Added a new tab for users to see their NFTs` `CHANGELOG entry: Fixed a bug that was causing some NFTs to flicker` (This helps the Release Engineer do their job more quickly and accurately) --> CHANGELOG entry: ## **Related issues** Fixes: ## **Manual testing steps** 1. Check ci -- no failure in those test should cause the ci job to fail ## **Screenshots/Recordings** <!-- If applicable, add screenshots and/or recordings to visualize the before and after of your change. --> ### **Before** <img width="2462" height="606" alt="image" src="https://github.com/user-attachments/assets/f166b436-bf02-429e-8bfc-6a85492f5dd1" /> <img width="780" height="493" alt="image" src="https://github.com/user-attachments/assets/9d5d44aa-bed1-4ec3-a646-091fc73b5b00" /> <!-- [screenshots/recordings] --> ### **After** <!-- [screenshots/recordings] --> ## **Pre-merge author checklist** - [x] I've followed [MetaMask Contributor Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Extension Coding Standards](https://github.com/MetaMask/metamask-extension/blob/main/.github/guidelines/CODING_GUIDELINES.md). - [x] I've completed the PR template to the best of my ability - [x] I’ve included tests if applicable - [x] I’ve documented my code using [JSDoc](https://jsdoc.app/) format if applicable - [x] I’ve applied the right labels on the PR (see [labeling guidelines](https://github.com/MetaMask/metamask-extension/blob/main/.github/guidelines/LABELING_GUIDELINES.md)). Not required for external contributors. ## **Pre-merge reviewer checklist** - [ ] I've manually tested the PR (e.g. pull and build branch, run the app, test code being changed). - [ ] I confirm that this PR addresses all acceptance criteria described in the ticket it closes and includes the necessary testing evidence such as recordings and or screenshots. <!-- CURSOR_SUMMARY --> --- > [!NOTE] > **Low Risk** > Test-only CI behavior change; no production or runtime logic is modified. > > **Overview** > Snap Simple Keyring e2e coverage is isolated into **tolerate-failure** specs so intermittent snap keyring crashes no longer fail CI, while the tests still run and failures are logged. > > The multichain **“should display wallet for Snap Keyring”** case moves from `multichain-account-list-menu.spec.ts` into `multichain-account-list-menu-snap-keyring.tolerate-failure.spec.ts`; the main multichain menu spec drops that scenario and related snap-only imports. Comments are added on existing `*.tolerate-failure.spec.ts` files noting that `run-e2e-test.js` treats paths containing `tolerate-failure` as non-blocking. > > <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit d2a0cbe. Bugbot is set up for automated code reviews on this repo. Configure [here](https://www.cursor.com/dashboard/bugbot).</sup> <!-- /CURSOR_SUMMARY -->
## **Description** Adds instrumentation for homepage critical user flow which is currently blank. This tracks balance and token list ready. A helper hook was added and uses existing trace wrappers and handles lifecycle completion, cleanup, etc. ## **Changelog** CHANGELOG entry: null ## **Related issues** Fixes: Related: CEUX-1356 ## **Manual testing steps** 1. Unlock the extension and open the homepage. 2. Switch accounts and enabled networks, including a testnet. 3. Verify the balance-ready and token-list-ready traces are emitted with `success` and `content_state` attributes. ## **Screenshots/Recordings** Not applicable. ### **Before** Not applicable. ### **After** Not applicable. ## **Pre-merge author checklist** - [x] I've followed MetaMask Contributor Docs and Extension Coding Standards. - [x] I've completed the PR template to the best of my ability. - [x] I've included tests where applicable. - [x] I've documented code using JSDoc format where applicable. - [x] I've applied the appropriate labels. ## **Pre-merge reviewer checklist** - [ ] I've manually tested the PR. - [ ] I confirm that this PR addresses the acceptance criteria and includes necessary testing evidence. ## **Validation** - Changed-file ESLint passed. - Focused Jest tests passed: 3 suites, 29 passed, 1 skipped. - oxfmt passed. - git diff --check passed. <!-- CURSOR_SUMMARY --> --- > [!NOTE] > **Low Risk** > Observability-only changes with bounded Sentry sampling; minor balance loading-state tweak in coin overview with no auth or payment impact. > > **Overview** > Adds **homepage performance tracing** so Sentry can measure when the wallet home is “ready” and when key sections show content. > > Introduces **`useTrace` / `useLayoutTrace`** and a **`TraceCoordinator`** that runs a parent **`Homepage Ready`** transaction until required child signals (`balance`, `tokens`) complete. **`useCoordinatedTrace`** emits nested **`Homepage Section Time To Content`** spans with `section_id`, `content_state` (filled/empty), and snake_cased attributes via new **`toSnakeCase`**. > > Wires this into **`AccountOverviewLayout`**, **`CoinOverview`** (balance ready after loading/empty-state logic, with a **`generationKey`** on account/network changes), and **`TokenList`**. Adds trace names/ops, a selector **`getSelectedAccountGroupNetworkGenerationKey`** for stable parent trace IDs, and **0.1% Sentry sample rates** for the new transaction names. > > **`coin-overview`** also tightens zero-fiat balance loading so the skeleton stays up until delay state is in sync when networks or delay flags change. > > <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit 3326750. Bugbot is set up for automated code reviews on this repo. Configure [here](https://www.cursor.com/dashboard/bugbot).</sup> <!-- /CURSOR_SUMMARY -->
<!-- Please submit this PR as a draft initially. Do not mark it as "Ready for review" until the template has been completely filled out, and PR status checks have passed at least once. --> ## **Description** (Behind a feature flag) Adds a MetaMask ticker widget for supported token `$SYMBOL`s on X. Supported tokens display live market data and open a widget with token details and actions to open the asset or swap flow in MetaMask. The widget runs in an extension iframe rather than rendering its React tree directly into the host page. Background handlers own token search, price history, navigation, preference updates, and feature availability. This change also adds the required extension manifests, Webpack entries, LavaMoat configuration, settings preference, and threat model. ## **Changelog** CHANGELOG entry: Added x.com ticker widget <!-- ## **Related issues** Fixes: --> ## **Manual testing steps** 1. Load the extension and sign in to X. 2. Open a post containing a supported cashtag, such as `$BTC`, and verify the cashtag displays its current price and 24-hour change. 3. Hover or focus the cashtag and verify the widget opens with token details and a price chart. 4. Verify the asset-details and swap actions open the expected MetaMask route in both popup and side-panel modes. 5. Open a cashtag with multiple matching assets, select **View similar tokens**, and verify the results table appears. 6. Disable the ticker widget from its menu, confirm the dialog, and verify cashtags return to their standard X appearance. 7. Re-enable the ticker widget from **Settings → Preferences and display** and verify the enhanced cashtags return. ## **Screenshots/Recordings** ### **Before** Standard X cashtags render as plain links. ### **After** |Pill|Widget| |---|---| |<img width="169" height="52" alt="image" src="https://github.com/user-attachments/assets/ee9d8cbf-f7b8-433b-a5ad-4c91a4173658" />|<img width="575" height="444" alt="image" src="https://github.com/user-attachments/assets/3fb68938-5c45-4985-a00f-4eb2202f6062" />| ## **Pre-merge author checklist** - [x] I've followed [MetaMask Contributor Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Extension Coding Standards](https://github.com/MetaMask/metamask-extension/blob/main/.github/guidelines/CODING_GUIDELINES.md). - [x] I've completed the PR template to the best of my ability - [x] I’ve included tests if applicable - [x] I’ve documented my code using [JSDoc](https://jsdoc.app/) format if applicable - [ ] I’ve applied the right labels on the PR (see [labeling guidelines](https://github.com/MetaMask/metamask-extension/blob/main/.github/guidelines/LABELING_GUIDELINES.md)). Not required for external contributors. ## **Pre-merge reviewer checklist** - [ ] I've manually tested the PR (e.g. pull and build branch, run the app, test code being changed). - [ ] I confirm that this PR addresses all acceptance criteria described in the ticket it closes and includes the necessary testing evidence such as recordings and or screenshots. <!-- CURSOR_SUMMARY --> --- > [!NOTE] > **High Risk** > Introduces third-party page injection on x.com, relaxed CSP frame-ancestors, and new runtime messaging that opens swap/asset flows—security-sensitive surface area despite sender checks and feature gating. > > **Overview** > Adds a **feature-flagged MetaMask ticker widget on X** that enhances `$SYMBOL` cashtags in tweets with live price pills and a hover/focus popover, without injecting the full React UI into the host page. > > **On-page behavior:** An X content-script path scans tweet cashtag links, resolves tokens via background messaging, and injects styled pills plus a shadow-DOM popover anchored to the clicked cashtag. The popover loads a new web-accessible `cashtag-widget.html` iframe that renders token details, a 1D price chart, similar-token picker, swap/view-details actions, and disable-with-confirmation. > > **Background & policy:** A new cashtag background bridge validates message senders (X top frame vs widget iframe), gates on Basic Functionality + `cashtagInjection` + `showTickerWidget`, fetches token search and price history from MetaMask APIs, broadcasts enable/disable to X tabs, tracks widget analytics, and opens swap/asset routes in side panel, popup, or tab. Manifest/CSP updates expose the widget HTML to `x.com` and allow framing from X; disabling external services now clears `showTickerWidget`. > > **Build/tooling:** Webpack treats cashtag page CSS as injectable strings, builds widget CSS with inlined design tokens, registers isolated HTML/LavaMoat lockdown for the iframe bundle, and adds extensive unit tests plus a shared overflow menu component. > > <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit 25a0768. Bugbot is set up for automated code reviews on this repo. Configure [here](https://www.cursor.com/dashboard/bugbot).</sup> <!-- /CURSOR_SUMMARY --> --------- Co-authored-by: Cursor <cursoragent@cursor.com>
## **Description**
The Perps market list re-sorted itself on every live price tick, so rows
swapped places while being read. Sorting by 24h price change was the
worst case, because the ranking runs on `change24hPercent` — the exact
field the price stream rewrites several times a second.
`usePerpsLiveMarketListData` returns a fresh `markets` array on every
tick with `price` and `change24hPercent` overwritten. `displayedMarkets`
listed `allMarkets` as a dependency and called `sortMarkets` inside it,
so every tick produced a new ranking and re-rendered the rows in a new
order.
This separates filtering from ranking. Filtering still tracks live data.
The row order is established from a snapshot and then held: a new order
is computed only when the user changes what the ranking means (sort
field, sort direction, category filter, search query) or when the set of
matching markets itself changes. Live values are projected onto that
frozen order, so prices and percentages keep updating in place while
rows stay put.
Four tests cover it: the order holds across a tick that would re-rank,
values still update on a row that has not moved, changing the sort
re-ranks on the ticked values rather than the stale snapshot, and a
newly listed market is ranked into position rather than appended.
One thing to look at in review: `rankingSnapshot` is a deliberately
stale memo carrying an `eslint-disable` for
`react-hooks/exhaustive-deps`. Reading current markets through a ref
instead is rejected by this repo's `react-hooks/refs` rule ("Cannot
access refs during render"), and adding `matchingMarkets` back as a
dependency reintroduces the bug. The comment above it says so.
## **Changelog**
CHANGELOG entry: Fixed the Perps market list reordering rows while live
prices updated
## **Related issues**
Fixes:
[TAT-3934](https://consensyssoftware.atlassian.net/browse/TAT-3934)
## **Manual testing steps**
1. Open the Perps market list.
2. Sort by Price change.
3. Watch for 30 seconds without touching anything. Percentages and
prices should keep updating; no row should change position.
4. Change the sort field or direction. The list should immediately
re-rank on the values currently on screen, not on the values from when
the page was opened.
5. Switch category filters, then type in search. Each should produce a
correctly ordered list.
6. Repeat with Volume, Open interest and Funding rate to confirm nothing
regressed.
## **Screenshots/Recordings**
### **Before**
Recording of the current behavior is attached to
[TAT-3934](https://consensyssoftware.atlassian.net/browse/TAT-3934).
### **After**
Video shows DASH and PEOPLE hold their sort even after PEOPLE's price
change exceeds DASH's. Only after we resort do they swap position in the
UI.
https://www.loom.com/share/44de2b59cd1b4e9aa3fd69622caf0f23
## **Pre-merge author checklist**
- [x] I've followed [MetaMask Contributor
Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask
Extension Coding
Standards](https://github.com/MetaMask/metamask-extension/blob/main/.github/guidelines/CODING_GUIDELINES.md).
- [x] I've completed the PR template to the best of my ability
- [x] I’ve included tests if applicable
- [x] I’ve documented my code using [JSDoc](https://jsdoc.app/) format
if applicable
- [x] I’ve applied the right labels on the PR (see [labeling
guidelines](https://github.com/MetaMask/metamask-extension/blob/main/.github/guidelines/LABELING_GUIDELINES.md)).
Not required for external contributors.
## **Pre-merge reviewer checklist**
- [ ] I've manually tested the PR (e.g. pull and build branch, run the
app, test code being changed).
- [ ] I confirm that this PR addresses all acceptance criteria described
in the ticket it closes and includes the necessary testing evidence such
as recordings and or screenshots.
[TAT-3934]:
https://consensyssoftware.atlassian.net/browse/TAT-3934?atlOrigin=eyJpIjoiNWRkNTljNzYxNjVmNDY3MDlhMDU5Y2ZhYzA5YTRkZjUiLCJwIjoiZ2l0aHViLWNvbS1KU1cifQ
<!-- CURSOR_SUMMARY -->
---
> [!NOTE]
> **Medium Risk**
> Changes core market-list ordering logic for live streams; wrong
ranking keys could show stale order or miss re-ranks when markets appear
or go live.
>
> **Overview**
> **Stops the Perps market list from re-sorting on every live price
tick** while still updating prices and 24h change in place—fixing rows
jumping under the reader when sorted by price change.
>
> Filtering/search still tracks live `allMarkets`; **row order is
frozen** until the user changes sort, filter, or search, the set of
matching symbols changes, or the stream first goes live (`isLive`). A
`rankingSnapshot` captures markets at those moments; `displayedMarkets`
maps the frozen symbol order onto current live values.
>
> Adds a **“row order under live updates”** test suite (stable order
across ticks, in-place value updates, re-rank on sort change / new
listings / first live tick).
>
> <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit
a6624c3. Bugbot is set up for automated
code reviews on this repo. Configure
[here](https://www.cursor.com/dashboard/bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
---------
Co-authored-by: Claude Sonnet 5 <noreply@anthropic.com>
<!-- Please submit this PR as a draft initially. Do not mark it as "Ready for review" until the template has been completely filled out, and PR status checks have passed at least once. --> ## **Description** Stellar was missing from send loader config. <!-- Write a short description of the changes included in this pull request, also include relevant motivation and context. Have in mind the following questions: 1. What is the reason for the change? 2. What is the improvement/solution? --> ## **Changelog** <!-- If this PR is not End-User-Facing and should not show up in the CHANGELOG, you can choose to either: 1. Write `CHANGELOG entry: null` 2. Label with `no-changelog` If this PR is End-User-Facing, please write a short User-Facing description in the past tense like: `CHANGELOG entry: Added a new tab for users to see their NFTs` `CHANGELOG entry: Fixed a bug that was causing some NFTs to flicker` (This helps the Release Engineer do their job more quickly and accurately) --> CHANGELOG entry: Added stellar in send loader config ## **Related issues** Fixes: #46812 ## **Manual testing steps** 1. Go to this page... 2. 3. ## **Screenshots/Recordings** <!-- If applicable, add screenshots and/or recordings to visualize the before and after of your change. --> ### **Before** <!-- [screenshots/recordings] --> ### **After** <!-- [screenshots/recordings] --> ## **Pre-merge author checklist** - [ ] I've followed [MetaMask Contributor Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Extension Coding Standards](https://github.com/MetaMask/metamask-extension/blob/main/.github/guidelines/CODING_GUIDELINES.md). - [ ] I've completed the PR template to the best of my ability - [ ] I’ve included tests if applicable - [ ] I’ve documented my code using [JSDoc](https://jsdoc.app/) format if applicable - [ ] I’ve applied the right labels on the PR (see [labeling guidelines](https://github.com/MetaMask/metamask-extension/blob/main/.github/guidelines/LABELING_GUIDELINES.md)). Not required for external contributors. ## **Pre-merge reviewer checklist** - [ ] I've manually tested the PR (e.g. pull and build branch, run the app, test code being changed). - [ ] I confirm that this PR addresses all acceptance criteria described in the ticket it closes and includes the necessary testing evidence such as recordings and or screenshots. <!-- CURSOR_SUMMARY --> --- > [!NOTE] > **Low Risk** > Small parity fix in confirmation routing logic with a matching test; no auth or payment changes. > > **Overview** > **Fixes Stellar send confirmations not auto-opening** by treating `STELLAR_WALLET_SNAP_ID` like Bitcoin, Solana, and Tron in the send confirmation `Loader`. > > When an unapproved templated confirmation comes from the Stellar wallet snap, the loader now redirects to the v-next confirmation route (`CONFIRMATION_V_NEXT_ROUTE/{id}`) instead of staying on the loading screen. A unit test mirrors the existing Bitcoin/Solana cases for Stellar pending sends. > > <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit 141a6bc. Bugbot is set up for automated code reviews on this repo. Configure [here](https://www.cursor.com/dashboard/bugbot).</sup> <!-- /CURSOR_SUMMARY -->
…46862) ## **Description** Money account deposit funnels filter transaction events on `transaction_type = money_account_deposit`, but those deposits are submitted with `addTransactionBatch`. The parent type is `batch`, so Transaction Added, Submitted, and Finalized were recorded as `batch`. This matches mobile: `getTransactionTypeValue` checks nested transaction types before falling back to the parent type. A deposit batch now reports `money_account_deposit`, and a withdrawal batch reports `money_account_withdraw`. Other batches still report `batch`. ## **Changelog** CHANGELOG entry: null ## **Related issues** Fixes: https://consensyssoftware.atlassian.net/browse/CONF-2117 ## **Manual testing steps** 1. Build the extension and load it in Chrome. 2. Open the money account and start a deposit. Confirm it with a pay token selected. 3. In the MetaMetrics debugger, inspect Transaction Added, Transaction Submitted, and Transaction Finalized for that confirmation. 4. Verify `transaction_type` is `money_account_deposit`. 5. Repeat a money account withdrawal and verify `transaction_type` is `money_account_withdraw`. 6. Confirm an unrelated batch transaction and verify `transaction_type` is still `batch`. <!-- ## **Screenshots/Recordings** ### **Before** ### **After** --> ## **Pre-merge author checklist** - [x] I've followed [MetaMask Contributor Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Extension Coding Standards](https://github.com/MetaMask/metamask-extension/blob/main/.github/guidelines/CODING_GUIDELINES.md). - [x] I've completed the PR template to the best of my ability - [x] I’ve included tests if applicable - [x] I’ve documented my code using [JSDoc](https://jsdoc.app/) format if applicable - [x] I’ve applied the right labels on the PR (see [labeling guidelines](https://github.com/MetaMask/metamask-extension/blob/main/.github/guidelines/LABELING_GUIDELINES.md)). Not required for external contributors. ## **Pre-merge reviewer checklist** - [ ] I've manually tested the PR (e.g. pull and build branch, run the app, test code being changed). - [ ] I confirm that this PR addresses all acceptance criteria described in the ticket it closes and includes the necessary testing evidence such as recordings and or screenshots. <!-- CURSOR_SUMMARY --> --- > [!NOTE] > **Low Risk** > Analytics-only classification change in transaction metrics context; no transaction submission or signing logic is modified. > > **Overview** > **Transaction metrics** now classify money account pay flows correctly when they are submitted as batches (`addTransactionBatch`), instead of emitting `transaction_type: batch`. > > `determineTransactionTypeAndContractInteraction` inspects nested transactions via `hasTransactionType` and maps deposits and withdrawals to `money_account_deposit` and `money_account_withdraw`, aligned with mobile’s `getTransactionTypeValue`. Unrelated batches still report `batch`, and **retry** paths pass through the same nested lookup so retried deposit batches keep the money-account type. > > Unit tests cover batch approve+deposit, withdraw-only batches, direct money account types, non-pay batches, and retried deposit batches. > > <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit cb4e76d. Bugbot is set up for automated code reviews on this repo. Configure [here](https://www.cursor.com/dashboard/bugbot).</sup> <!-- /CURSOR_SUMMARY -->
## **Description** Returning from Add funds on Earn on your crypto left two identical Earn entries in history. The deposit confirmation is pushed on top of that page, and back replaced the confirmation entry with the same URL, so the first in-app back press stayed on Earn and only the second press reached Money home. Pushed confirmations (Money deposit and withdraw) now record `goBackAction=pop`. Back and auto-exit pop that history entry when there is already an in-app page underneath. Flows that open the confirmation with replace, such as Perps deposit and mUSD conversion, still return by replacing the entry with `goBackTo`. A confirmation that is the first history entry also still replaces, so a notification window does not navigate out of the extension. ## **Changelog** CHANGELOG entry: Fixed the back arrow on Earn on your crypto requiring two taps after adding a token ## **Related issues** Fixes: [CONF-2115](https://consensyssoftware.atlassian.net/browse/CONF-2115) Fixes: #46672 ## **Manual testing steps** 1. Run the extension and open Money. 2. In Earn on your crypto, click View all. 3. Click Add on any token. 4. Click the back arrow on the add-funds confirmation. 5. On Earn on your crypto, click the back arrow once. 6. Confirm you return to Money home on that first press. 7. Repeat from Money home using Add funds, then back, and confirm one back press leaves the confirmation for the page you started from. 8. From a Perps order screen, open Add funds and press back. Confirm you return to the order screen in one press. <!-- ## **Screenshots/Recordings** ### **Before** ### **After** --> ## **Pre-merge author checklist** - [x] I've followed [MetaMask Contributor Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Extension Coding Standards](https://github.com/MetaMask/metamask-extension/blob/main/.github/guidelines/CODING_GUIDELINES.md). - [x] I've completed the PR template to the best of my ability - [x] I’ve included tests if applicable - [x] I’ve documented my code using [JSDoc](https://jsdoc.app/) format if applicable - [x] I’ve applied the right labels on the PR (see [labeling guidelines](https://github.com/MetaMask/metamask-extension/blob/main/.github/guidelines/LABELING_GUIDELINES.md)). Not required for external contributors. ## **Pre-merge reviewer checklist** - [ ] I've manually tested the PR (e.g. pull and build branch, run the app, test code being changed). - [ ] I confirm that this PR addresses all acceptance criteria described in the ticket it closes and includes the necessary testing evidence such as recordings and or screenshots. [CONF-2115]: https://consensyssoftware.atlassian.net/browse/CONF-2115?atlOrigin=eyJpIjoiNWRkNTljNzYxNjVmNDY3MDlhMDU5Y2ZhYzA5YTRkZjUiLCJwIjoiZ2l0aHViLWNvbS1KU1cifQ <!-- CURSOR_SUMMARY --> --- > [!NOTE] > **Medium Risk** > Changes shared confirmation exit navigation used by cancel, auto-exit, and Money/Perps flows; behavior is well covered by new tests but incorrect edge cases could still affect back-stack UX across wallet-initiated confirmations. > > **Overview** > Fixes broken in-app back navigation after leaving **pushed** transaction confirmations (e.g. Money Earn add funds), where exiting always **replaced** the confirmation with `goBackTo` and duplicated the origin route in history. > > Pushed entry points now tag the URL with **`goBackAction=pop`** (`navigateToTransaction`), and a shared **`navigateConfirmationExit`** decides whether to **`navigate(-1)`** or **`replace` with `goBackTo` / home** using the captured `goBackAction` and React Router `location.key` (`default` still replaces so notification windows do not leave the extension). **Confirm context** auto-exit and **`useConfirmActions` cancel/back** use this helper; cancel with `navigateBackToPreviousPage` also **suppresses auto-exit** to avoid double navigation. Flows that open confirmations with **replace** (Perps deposit, mUSD) stay on the replace path when `goBackAction` is absent. > > <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit 493f66a. Bugbot is set up for automated code reviews on this repo. Configure [here](https://www.cursor.com/dashboard/bugbot).</sup> <!-- /CURSOR_SUMMARY -->
## **Description** <!-- Write a short description of the changes included in this pull request, also include relevant motivation and context. Have in mind the following questions: 1. What is the reason for the change? 2. What is the improvement/solution? --> When the MetaMask side panel defers the Ledger connect flow to the expanded tab, it stayed on the add-wallet screen after account selection finished, instead of returning to a sensible screen. This PR navigates the side panel to the default route at handoff so it lands on home once the hardware wallet flow completes in the expanded tab: - `ui/pages/multichain-accounts/choose-new-wallet-type/choose-new-wallet-type-page.tsx`: after handing off the hardware wallet flow with `keepWindowOpen` (side panel), call `navigate(DEFAULT_ROUTE)`. The popup is unaffected because it closes itself on handoff and needs no navigation. - `choose-new-wallet-type-page.test.tsx`: added a unit test asserting the side panel navigates to `DEFAULT_ROUTE` on handoff. Refs: [MUL-2231](https://consensyssoftware.atlassian.net/browse/MUL-2231?atlOrigin=eyJpIjoiY2I3MTUyMzYzZDNmNDU1ZGE2MzM5MjMyYTI0NDcwNDMiLCJwIjoiaiJ9) ## **Changelog** <!-- If this PR is not End-User-Facing and should not show up in the CHANGELOG, you can choose to either: 1. Write `CHANGELOG entry: null` 2. Label with `no-changelog` If this PR is End-User-Facing, please write a short User-Facing description in the past tense like: `CHANGELOG entry: Added a new tab for users to see their NFTs` `CHANGELOG entry: Fixed a bug that was causing some NFTs to flicker` (This helps the Release Engineer do their job more quickly and accurately) --> CHANGELOG entry: Fixed a bug that was leaving the MetaMask side panel on the add-wallet screen after connecting a hardware wallet in the expanded tab. ## **Related issues** Fixes: MUL-2231 ## **Manual testing steps** 1. Run the extension (`yarn start`) and load it in Chrome. 2. Open MetaMask via the side panel UI. 3. In the side panel, go to the account menu → Add a new wallet, so you land on the "choose new wallet type" screen. 4. Select **Hardware wallet** — the flow hands off to the expanded tab with the Ledger connect screen. 5. Complete (or cancel) account selection in the expanded tab, then look back at the side panel. 6. Verify the side panel now shows the home screen (default route) instead of staying on the add-wallet screen. 7. Repeat steps 2–4 using the popup UI: verify the popup closes itself on handoff and the behavior is unchanged. ## **Screenshots/Recordings** <!-- If applicable, add screenshots and/or recordings to visualize the before and after of your change. --> ### **Before** <!-- [screenshots/recordings] --> ### **After** <!-- [screenshots/recordings] --> ## **Pre-merge author checklist** - [x] I've followed [MetaMask Contributor Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Extension Coding Standards](https://github.com/MetaMask/metamask-extension/blob/main/.github/guidelines/CODING_GUIDELINES.md). - [x] I've completed the PR template to the best of my ability - [x] I’ve included tests if applicable - [ ] I’ve documented my code using [JSDoc](https://jsdoc.app/) format if applicable - [ ] I’ve applied the right labels on the PR (see [labeling guidelines](https://github.com/MetaMask/metamask-extension/blob/main/.github/guidelines/LABELING_GUIDELINES.md)). Not required for external contributors. ## **Pre-merge reviewer checklist** - [ ] I've manually tested the PR (e.g. pull and build branch, run the app, test code being changed). - [ ] I confirm that this PR addresses all acceptance criteria described in the ticket it closes and includes the necessary testing evidence such as recordings and or screenshots. [MUL-2231]: https://consensyssoftware.atlassian.net/browse/MUL-2231?atlOrigin=eyJpIjoiNWRkNTljNzYxNjVmNDY3MDlhMDU5Y2ZhYzA5YTRkZjUiLCJwIjoiZ2l0aHViLWNvbS1KU1cifQ <!-- CURSOR_SUMMARY --> --- > [!NOTE] > **Low Risk** > Small, side-panel-only navigation after an existing browser handoff; popup and fullscreen paths are unchanged. > > **Overview** > Fixes side panel UX when **Hardware wallet** opens the connect flow in an expanded tab: the panel used to stay on the add-wallet screen after handoff. > > After `openExtensionInBrowser` with `keepWindowOpen` (side panel only), the choose-new-wallet-type page now calls `navigate(DEFAULT_ROUTE)` so the panel shows home while Ledger setup runs in the tab. Popup handoff is unchanged (no extra navigation). > > Tests cover side panel navigation to `DEFAULT_ROUTE` and assert popup mode does not navigate there. > > <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit 1431737. Bugbot is set up for automated code reviews on this repo. Configure [here](https://www.cursor.com/dashboard/bugbot).</sup> <!-- /CURSOR_SUMMARY -->
…46840) <!-- Please submit this PR as a draft initially. Do not mark it as "Ready for review" until the template has been completely filled out, and PR status checks have passed at least once. --> ## **Description** <!-- Write a short description of the changes included in this pull request, also include relevant motivation and context. Have in mind the following questions: 1. What is the reason for the change? 2. What is the improvement/solution? --> Fixes Arc `USDC` handling in the Swap asset picker. Arc’s native `USDC` balance is stored under the native `slip44` asset representation, while Swaps must use the validated ERC-20 wrapper token. The asset picker now keeps the native Arc asset hidden from the visible list, but still uses it as a balance source for the ERC-20 `USDC` entry shown in Swap. Also updates the asset details navigation from the Swap asset picker so clicking the `i` icon for Arc USDC opens the native Arc asset details route. This makes the token details page use the same asset metadata and icon as when opened from the main Tokens page. ## **Changelog** <!-- If this PR is not End-User-Facing and should not show up in the CHANGELOG, you can choose to either: 1. Write `CHANGELOG entry: null` 2. Label with `no-changelog` If this PR is End-User-Facing, please write a short User-Facing description in the past tense like: `CHANGELOG entry: Added a new tab for users to see their NFTs` `CHANGELOG entry: Fixed a bug that was causing some NFTs to flicker` (This helps the Release Engineer do their job more quickly and accurately) --> CHANGELOG entry: Show Arc USDC balance and details from native asset in swap asset picker ## **Related issues** Fixes: ## **Manual testing steps** 1. Build and run the extension. 2. Use an account with an Arc USDC balance. 3. Open Swap. 4. Open the source asset picker. 5. Select or filter to Arc. 6. Verify the USDC row shows the user’s USDC balance instead of an empty line. 7. Verify other Arc tokens with balances, such as EURC, still show their balances. 8. Click the `i` icon on the Arc USDC row. 9. Verify the token details page opens and the USDC icon is displayed correctly. 10. From the main Tokens page, open Arc USDC details and verify the same icon/details are shown. ## **Screenshots/Recordings** <!-- If applicable, add screenshots and/or recordings to visualize the before and after of your change. --> ### **Before** <!-- [screenshots/recordings] --> <img width="350" height="377" alt="46840 Before_1" src="https://github.com/user-attachments/assets/4f0c15e5-1fa3-476d-9366-79ff82cc0ef8" /> <img width="350" height="377" alt="46840 Before_2" src="https://github.com/user-attachments/assets/1a38c5a5-d656-4507-b2e5-2addc5b0e355" /> ### **After** <!-- [screenshots/recordings] --> <img width="350" height="377" alt="46840 After_1" src="https://github.com/user-attachments/assets/c17f8e2d-f59e-4faf-9295-ac17c89d3efc" /> <img width="350" height="377" alt="46840 After_2" src="https://github.com/user-attachments/assets/3945d132-c7a7-4520-a1cf-b38ffab6bdf0" /> ## **Pre-merge author checklist** - [X] I've followed [MetaMask Contributor Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Extension Coding Standards](https://github.com/MetaMask/metamask-extension/blob/main/.github/guidelines/CODING_GUIDELINES.md). - [X] I've completed the PR template to the best of my ability - [X] I’ve included tests if applicable - [X] I’ve documented my code using [JSDoc](https://jsdoc.app/) format if applicable - [X] I’ve applied the right labels on the PR (see [labeling guidelines](https://github.com/MetaMask/metamask-extension/blob/main/.github/guidelines/LABELING_GUIDELINES.md)). Not required for external contributors. ## **Pre-merge reviewer checklist** - [X] I've manually tested the PR (e.g. pull and build branch, run the app, test code being changed). - [X] I confirm that this PR addresses all acceptance criteria described in the ticket it closes and includes the necessary testing evidence such as recordings and or screenshots. <!-- CURSOR_SUMMARY --> --- > [!NOTE] > **Medium Risk** > Changes swap balance resolution and asset routing for Arc USDC; incorrect aliasing could show wrong balances or open the wrong details page, but scope is limited to Arc bridge/swap flows with new tests. > > **Overview** > Fixes Swap/Bridge handling when Arc **USDC** is stored as the native `slip44` balance but swaps must use the validated **ERC-20 wrapper** CAIP ID. > > New Arc helpers map bridge lookup IDs to wallet balances (`getArcBridgeAssetIdAliases`) and rewrite asset-details routes from ERC-20 USDC to the native asset ID (`getArcAssetDetailsRouteAssetId`). Bridge asset selectors now build balances from **hidden** assets (including native Arc) while the picker list still filters them out; `getBridgeAssetsByAssetId` aliases native USDC onto the ERC-20 entry with **6-decimal** bridge metadata so the visible USDC row shows the correct balance. > > `navigateToAssetPage` uses the native route when opening details from the picker info icon, matching the main Tokens page icon/metadata. Tests cover selector aliasing and navigation. > > <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit 4bbaaa1. Bugbot is set up for automated code reviews on this repo. Configure [here](https://www.cursor.com/dashboard/bugbot).</sup> <!-- /CURSOR_SUMMARY --> --------- Co-authored-by: Cursor Agent <cursoragent@cursor.com> Co-authored-by: Gabriele Del Monte <gabrieledm@users.noreply.github.com>
## **Description** Part 7 of the 18-part assets-unification stack. test(assets): cover unified compatibility selectors. This focused slice keeps the review below the 1,000 changed-line limit while preserving the final behavior of the original PR. ## **Changelog** CHANGELOG entry: null <!-- ## **Related issues** Fixes: --> ## **Manual testing steps** 1. Build and load the extension. 2. Unlock or onboard a wallet. 3. Verify home balances and token lists render. 4. Open send and bridge token selectors and verify assets are available. <!-- ## **Screenshots/Recordings** ### **Before** ### **After** --> ## **Pre-merge author checklist** - [x] I have followed MetaMask coding standards. - [x] I have completed the PR template. - [x] I have included tests where applicable. ## **Pre-merge reviewer checklist** - [ ] I have manually tested the PR. - [ ] I confirm the acceptance criteria and testing evidence. <!-- CURSOR_SUMMARY --> --- > [!NOTE] > **Low Risk** > Test-only changes to assets-migration selector coverage; no production code modified. > > **Overview** > Refactors **`assets-migration.test.ts`** so the first batch of unified-state compatibility selectors (`getAccountTrackerControllerAccountsByChainId`, token list/ignore/balance selectors, and `getMultiChainAssetsControllerAccountsAssets`) are tested only on the **enabled** unified-assets path. > > **Removes** the nested `when assets unify state feature is disabled` suites that asserted legacy state passthrough for those selectors. **Flattens** describe blocks (happy path at top level, `edge cases` renamed) and **standardizes** fixtures with shared `enabledFlags` instead of inline `remoteFeatureFlags`. > > **Tightens** `makeMockPrice` with a `FungibleAssetPrice`-typed helper (including `usdPrice` and optional `null` overrides for non-finite market data). Production selector code is unchanged; this slice is test-only. > > <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit ef46843. Bugbot is set up for automated code reviews on this repo. Configure [here](https://www.cursor.com/dashboard/bugbot).</sup> <!-- /CURSOR_SUMMARY --> --------- Co-authored-by: Cursor <cursoragent@cursor.com>
<!-- Please submit this PR as a draft initially. Do not mark it as "Ready for review" until the template has been completely filled out, and PR status checks have passed at least once. --> ## **Description** E2E boots with the synced production remote flags. `stellarAccounts` is on for app 13.53.0, so the default wallet now has a Stellar account. Startup calls a new host, rewards stores that account, and two specs still expected the old account count and connect grants. **Root cause:** - E2E boots with the synced production remote flags. - stellarAccounts is now enabled for app 13.53.0 (minimumVersion 13.50.0). - Wallet init turns on the Stellar provider and creates a Stellar pubnet account. - That boot calls stellar-mainnet.infura.io, which was missing from the privacy snapshot. - Rewards stores that account, and the default fixture schema did not contain it. - DappViewed counts internal accounts, so number_of_accounts is 5. The spec still expected 4. - Default connect grants every non-test network that has an account, so the caveat now includes stellar:pubnet. The spec still expected only EVM, Solana, Bitcoin, and Tron. **Solution:** - Add stellar-mainnet.infura.io to privacy-snapshot.json so the startup request is allowed. - Add the Stellar rewards account to default-fixture.json and ignore its lastFreshOptInStatusCheck timestamp so the fixture matches the new account. - Set METAMASK_IDENTITIES to 5 in dapp-viewed.spec.ts so DappViewed expects the Stellar account. - Add stellar:pubnet to DEFAULT_PERMITTED_CAIP_CHAIN_IDS so the connect tests expect the Stellar grant. ## **Changelog** CHANGELOG entry: null <!-- ## **Related issues** Fixes: --> ## **Manual testing steps** 1. Start a test build with `yarn start:test` if one is not already running. These specs are not Flask tests. 2. Run the dapp viewed metrics spec: ```bash SELENIUM_BROWSER=chrome yarn test:e2e:single test/e2e/tests/metrics/dapp-viewed.spec.ts --debug --leave-running ``` 3. Run the multiple provider connections spec: ```bash SELENIUM_BROWSER=chrome yarn test:e2e:single test/e2e/tests/connections/multiple-provider-connections.spec.ts --debug --leave-running ``` ## **Screenshots/Recordings** ### **Before** No product UI change. This PR only updates E2E snapshots, fixtures, and assertions. ### **After** No product UI change. This PR only updates E2E snapshots, fixtures, and assertions. ## **Pre-merge author checklist** - [ ] I've followed [MetaMask Contributor Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Extension Coding Standards](https://github.com/MetaMask/metamask-extension/blob/main/.github/guidelines/CODING_GUIDELINES.md). - [ ] I've completed the PR template to the best of my ability - [ ] I’ve included tests if applicable - [ ] I’ve documented my code using [JSDoc](https://jsdoc.app/) format if applicable - [ ] I’ve applied the right labels on the PR (see [labeling guidelines](https://github.com/MetaMask/metamask-extension/blob/main/.github/guidelines/LABELING_GUIDELINES.md)). Not required for external contributors. ## **Pre-merge reviewer checklist** - [ ] I've manually tested the PR (e.g. pull and build branch, run the app, test code being changed). - [ ] I confirm that this PR addresses all acceptance criteria described in the ticket it closes and includes the necessary testing evidence such as recordings and or screenshots. --------- Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com> Co-authored-by: Harry Le <43307514+LeVinhGithub@users.noreply.github.com> Co-authored-by: LeVinhGithub <levinh.hcmut@gmail.com> Co-authored-by: Cursor <cursoragent@cursor.com>
…6809) ## **Description** The gasless EIP-7702 relay flow signs delegations to `ANY_BENEFICIARY`, so there is no restriction on which address can submit the `redeemDelegations` call. - The 7702 publish hook now adds a `RedeemerEnforcer` caveat, which restricts redemption to the Sentinel relay signers (`cubistSigners` from the Sentinel `/networks` API), plus the delegatee if one is set. - If a chain has no relay signers, the hook throws before signing rather than falling back to an unrestricted delegation. - `convertTransactionToRedeemDelegations` accepts an optional `redeemers` list. Callers that don't pass it, such as enforced simulations and MetaMask Pay, are unchanged. Gas fee token estimates need to include the enforcer to match. That comes from MetaMask/core#10615, which needs to be released and bumped here. ## **Changelog** CHANGELOG entry: null ## **Related issues** Fixes: Depends on: MetaMask/core#10615 ## **Manual testing steps** 1. On a relay-enabled chain, submit a transaction paying gas with a gas fee token, or a sponsored transaction. 2. Confirm the relay submits and confirms it. 3. Confirm the `redeemDelegations` calldata sent to the relay includes the `RedeemerEnforcer` caveat, with the chain's relay signers as terms. ## **Screenshots/Recordings** ### **Before** ### **After** ## **Pre-merge author checklist** - [x] I've followed [MetaMask Contributor Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Extension Coding Standards](https://github.com/MetaMask/metamask-extension/blob/main/.github/guidelines/CODING_GUIDELINES.md). - [x] I've completed the PR template to the best of my ability - [x] I’ve included tests if applicable - [x] I’ve documented my code using [JSDoc](https://jsdoc.app/) format if applicable - [ ] I’ve applied the right labels on the PR (see [labeling guidelines](https://github.com/MetaMask/metamask-extension/blob/main/.github/guidelines/LABELING_GUIDELINES.md)). Not required for external contributors. ## **Pre-merge reviewer checklist** - [ ] I've manually tested the PR (e.g. pull and build branch, run the app, test code being changed). - [ ] I confirm that this PR addresses all acceptance criteria described in the ticket it closes and includes the necessary testing evidence such as recordings and or screenshots. <!-- CURSOR_SUMMARY --> --- > [!NOTE] > **High Risk** > Changes who may redeem signed delegations in the gasless relay path; misconfigured signers or caveat terms could block legitimate relays or weaken redemption restrictions. > > **Overview** > Gasless EIP-7702 relay delegations previously allowed **any** address to call `redeemDelegations` because delegations target `ANY_BENEFICIARY`. This change **locks redemption** to Sentinel relay signers. > > The **7702 publish hook** loads `cubistSigners` from Sentinel’s `/networks` API via new **`getSentinelSigners`**, and **aborts before signing** if the list is empty so the wallet never publishes an unrestricted delegation. It passes those addresses into **`convertTransactionToRedeemDelegations`** as optional **`redeemers`**, which **appends a `RedeemerEnforcer` caveat** (using `createRedeemerTerms`) on top of default or caller-supplied caveats; the optional **delegatee** is included and duplicates are deduped. Callers that omit **`redeemers`** behave as before. > > E2E mocks now return **`cubistSigners`** for relay tests, and **`@metamask/transaction-controller`** is bumped to **72.1.0** (aligned with gas-fee estimate enforcer support in core). > > <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit bba7d7c. Bugbot is set up for automated code reviews on this repo. Configure [here](https://www.cursor.com/dashboard/bugbot).</sup> <!-- /CURSOR_SUMMARY -->
## **Description** Ports [metamask-mobile#36412](MetaMask/metamask-mobile#36412): lets Money Account deposit **Max** be quoted atomically (`EXACT_OUTPUT`) instead of always forcing non-atomic. `atomic` is left unset — so Core applies its atomic default — only when **both** hold: 1. `confirmations_pay_extended.payStrategies.relay.atomicMaxEnabled` is on for the transaction type, and 2. the selected pay token → destination route matches `confirmations_relay_fixed_spread`. Otherwise Max keeps setting `atomic: false`, preserving today's behaviour. The route match only *predicts* the subsidy; Core verifies the returned quote and re-quotes non-atomically if it isn't subsidized. Also: the hint is refreshed if the flag changes while Max is armed, and clearing a payment override no longer overwrites it. > [!IMPORTANT] > **Depends on a separate dependency PR.** The Core implementation ships in `@metamask/transaction-pay-controller@29.1.0`; this branch is pinned to `27.1.1`, so the new code is inert until that lands. Merge/rebase this **after** the package bump. > > That PR must also rename the delegated messenger action `RampsController:getQuotes` → `getQuoteWithFees` (required by TPC 29) and bump `@metamask/ramps-controller` to `^23`, which is the first version exporting the matching action type. ## **Changelog** CHANGELOG entry: null ## **Related issues** - https://consensyssoftware.atlassian.net/browse/CONF-1949 - Core: MetaMask/core#10224 ## **Configuration** ```json { "payStrategies": { "relay": { "atomicMaxEnabled": { "default": false, "transactionTypes": { "moneyAccountDeposit": true } } } } } ``` Merge into the existing `confirmations_pay_extended` value. `transactionTypes` is a type→boolean **object, not an array** — an array silently leaves the gate off. ## **Manual testing steps** > Requires the dependency PR (see above). 1. Apply the flag config, and ensure `confirmations_relay_fixed_spread` has a matching route for your pay token (e.g. USDC → mUSD). 2. Money Account → Add funds → pick that pay token → press **Max**. 3. Verify the quote is atomic `EXACT_OUTPUT` (single quote, vault calls embedded). 4. Turn the gate off, reload, press **Max** → verify it falls back to non-atomic `EXACT_INPUT`. 5. Press **Max**, then switch to a pay token **not** in the fixed-spread config → verify it stays non-atomic. 6. With Max armed, toggle payment method to Money Account and back → verify an atomic-eligible Max is not forced back to non-atomic. 7. Press **Max**, then pick 50% or type an amount → verify the Max override is cleared. <!-- ## **Screenshots/Recordings** ### **Before** ### **After** --> ## **Pre-merge author checklist** - [x] I've followed [MetaMask Contributor Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Extension Coding Standards](https://github.com/MetaMask/metamask-extension/blob/main/.github/guidelines/CODING_GUIDELINES.md). - [x] I've completed the PR template to the best of my ability - [x] I’ve included tests if applicable - [x] I’ve documented my code using [JSDoc](https://jsdoc.app/) format if applicable - [ ] I’ve applied the right labels on the PR (see [labeling guidelines](https://github.com/MetaMask/metamask-extension/blob/main/.github/guidelines/LABELING_GUIDELINES.md)). Not required for external contributors. ## **Pre-merge reviewer checklist** - [ ] I've manually tested the PR (e.g. pull and build branch, run the app, test code being changed). - [ ] I confirm that this PR addresses all acceptance criteria described in the ticket it closes and includes the necessary testing evidence such as recordings and or screenshots. <!-- CURSOR_SUMMARY --> --- > [!NOTE] > **Medium Risk** > Changes Pay quoting hints and deposit Max behavior on money-account flows; defaults stay non-atomic when flags or routes do not match, but incorrect gating could affect quote mode and amounts. > > **Overview** > Enables **atomic Max** quoting for Money Account deposits when remote config allows it, instead of always forcing `atomic: false` on Max. > > The confirmation amount hook now derives **`isAtomicMaxAllowed`** from `confirmations_pay_extended.payStrategies.relay.atomicMaxEnabled` (per transaction type, including nested batches) **and** a fixed-spread route match via `confirmations_relay_fixed_spread`. That flag is passed into `setIsMaxAmount`; the background init leaves **`config.atomic` unset** (Core’s atomic default) only when atomic Max is allowed, otherwise it still sets `atomic: false`. A new **`setTransactionPayAtomic`** path refreshes the hint when the gate changes while Max is already armed, and **clearing a payment override** no longer overwrites an armed deposit Max’s atomic hint. > > **`getTokenAddress`** now resolves the destination from **`requiredAssets`** for vault-targeted deposit batches so route matching uses mUSD, not the parent `to`. > > <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit 00bb6c5. Bugbot is set up for automated code reviews on this repo. Configure [here](https://www.cursor.com/dashboard/bugbot).</sup> <!-- /CURSOR_SUMMARY -->
<!-- Please submit this PR as a draft initially. Do not mark it as "Ready for review" until the template has been completely filled out, and PR status checks have passed at least once. --> ## Description Onboarding journey Sentry p90s currently include user think-time, such as entering an SRP and choosing a password. This makes the metrics difficult to use for performance monitoring and creates misleading outliers in the State of Quality report. This change adds separate machine-time instrumentation while preserving the existing wall-clock journey traces. ### Changes - Added machine-time child traces for: - Existing SRP import - New SRP wallet creation - New social wallet creation - Added `onboarding.machine.ms` to the overall onboarding journey span. - Excluded failed spans and nested backup work from the aggregate to avoid double counting. - Preserved trace parent context across buffered Sentry traces. - Added `account_type` attributes to onboarding traces. - Added `perf_fix=trace-registry-v1` as a release-boundary marker for before/after comparisons. - Added lifecycle and aggregation tests. ### Metric semantics - Existing wall-clock journey traces continue measuring total user journey time, including think-time. - Machine-time child spans measure only application work: - SRP import: `importWithRecoveryPhrase` duration. - Wallet creation: `createNewAccount` duration. - `onboarding.machine.ms` contains the sum of successful machine-time child spans for the journey. ## Changelog CHANGELOG entry: null ## Related issues Fixes: ## Manual testing steps 1. Load the extension and start a fresh onboarding flow. 2. Complete an existing SRP import. 3. Repeat with new SRP wallet creation and social wallet creation. 4. Confirm all onboarding flows complete normally without navigation regressions. 5. Verify that no user-facing UI behavior has changed. ## Screenshots/Recordings Not applicable. This is an observability-only change with no user-facing UI changes. ## Testing - `yarn lint:tsc` - `yarn lint:changed:fix` - `yarn test:unit shared/lib/trace.test.ts ui/pages/onboarding-flow/create-password/create-password.test.tsx --runInBand --watchman=false` - 64 focused tests passed. Live Sentry verification and State of Quality/watchlist query alignment will be performed separately. <!-- Write a short description of the changes included in this pull request, also include relevant motivation and context. Have in mind the following questions: 1. What is the reason for the change? 2. What is the improvement/solution? --> ## **Changelog** <!-- If this PR is not End-User-Facing and should not show up in the CHANGELOG, you can choose to either: 1. Write `CHANGELOG entry: null` 2. Label with `no-changelog` If this PR is End-User-Facing, please write a short User-Facing description in the past tense like: `CHANGELOG entry: Added a new tab for users to see their NFTs` `CHANGELOG entry: Fixed a bug that was causing some NFTs to flicker` (This helps the Release Engineer do their job more quickly and accurately) --> CHANGELOG entry: null ## **Related issues** Fixes: ## **Manual testing steps** 1. Go to this page... 2. 3. ## **Screenshots/Recordings** <!-- If applicable, add screenshots and/or recordings to visualize the before and after of your change. --> ### **Before** <!-- [screenshots/recordings] --> ### **After** <!-- [screenshots/recordings] --> ## **Pre-merge author checklist** - [x] I've followed [MetaMask Contributor Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Extension Coding Standards](https://github.com/MetaMask/metamask-extension/blob/main/.github/guidelines/CODING_GUIDELINES.md). - [x] I've completed the PR template to the best of my ability - [x] I’ve included tests if applicable - [x] I’ve documented my code using [JSDoc](https://jsdoc.app/) format if applicable - [x] I’ve applied the right labels on the PR (see [labeling guidelines](https://github.com/MetaMask/metamask-extension/blob/main/.github/guidelines/LABELING_GUIDELINES.md)). Not required for external contributors. ## **Pre-merge reviewer checklist** - [ ] I've manually tested the PR (e.g. pull and build branch, run the app, test code being changed). - [ ] I confirm that this PR addresses all acceptance criteria described in the ticket it closes and includes the necessary testing evidence such as recordings and or screenshots. <!-- CURSOR_SUMMARY --> --- > [!NOTE] > **Low Risk** > Observability-only changes to onboarding tracing and metrics buffering; wallet flows and navigation logic are largely unchanged aside from trace wrappers around existing async calls. > > **Overview** > Adds **onboarding machine-time** Sentry instrumentation so performance metrics can separate application work from user think-time, while keeping existing wall-clock journey traces. > > The trace layer now aggregates successful “machine” child spans into `onboarding.machine.ms` on `OnboardingJourneyOverall` (excluding failures, password/OAuth interaction spans, and double-counted nested backup work), and exposes `getTraceContext` / `annotateTrace` plus mobile-aligned trace names for SRP create/import duration. **Create password** starts and ends buffered child traces around `createNewAccount` and `importWithRecoveryPhrase` with `account_type` and journey parent context; **welcome** and **onboarding flow** attach `account_type` / `perf_fix: trace-registry-v1` on related spans. > > **SentryTracingService** no longer drops serialized `{ _name, _id }` parent context when buffering pre–metrics-opt-in traces, so nested spans still link after flush. Unit tests cover aggregation rules, buffering, and UI trace wiring. > > <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit 53986a9. Bugbot is set up for automated code reviews on this repo. Configure [here](https://www.cursor.com/dashboard/bugbot).</sup> <!-- /CURSOR_SUMMARY -->
<!-- Please submit this PR as a draft initially. Do not mark it as "Ready for review" until the template has been completely filled out, and PR status checks have passed at least once. --> ## **Description** This PR recreates the stale hid object that isn't removed when the webhid permission has been removed. <!-- Write a short description of the changes included in this pull request, also include relevant motivation and context. Have in mind the following questions: 1. What is the reason for the change? 2. What is the improvement/solution? --> ## **Changelog** <!-- If this PR is not End-User-Facing and should not show up in the CHANGELOG, you can choose to either: 1. Write `CHANGELOG entry: null` 2. Label with `no-changelog` If this PR is End-User-Facing, please write a short User-Facing description in the past tense like: `CHANGELOG entry: Added a new tab for users to see their NFTs` `CHANGELOG entry: Fixed a bug that was causing some NFTs to flicker` (This helps the Release Engineer do their job more quickly and accurately) --> CHANGELOG entry: fix ledger connection when permission has been revoked. ## **Related issues** Fixes: ## **Manual testing steps** 1. Connect with a ledger account 2. Go to site settings and block the webhid connection 3. See that connection modal popup when trying to use the device 4. Reenable webhid 5. See the connection is working again. ## **Screenshots/Recordings** <!-- If applicable, add screenshots and/or recordings to visualize the before and after of your change. --> ### **Before** <!-- [screenshots/recordings] --> ### **After** <!-- [screenshots/recordings] --> ## **Pre-merge author checklist** - [x] I've followed [MetaMask Contributor Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Extension Coding Standards](https://github.com/MetaMask/metamask-extension/blob/main/.github/guidelines/CODING_GUIDELINES.md). - [x] I've completed the PR template to the best of my ability - [x] I’ve included tests if applicable - [x] I’ve documented my code using [JSDoc](https://jsdoc.app/) format if applicable - [x] I’ve applied the right labels on the PR (see [labeling guidelines](https://github.com/MetaMask/metamask-extension/blob/main/.github/guidelines/LABELING_GUIDELINES.md)). Not required for external contributors. ## **Pre-merge reviewer checklist** - [ ] I've manually tested the PR (e.g. pull and build branch, run the app, test code being changed). - [ ] I confirm that this PR addresses all acceptance criteria described in the ticket it closes and includes the necessary testing evidence such as recordings and or screenshots. <!-- CURSOR_SUMMARY --> --- > [!NOTE] > **Medium Risk** > Changes core offscreen Ledger connection lifecycle (caching, teardown races, WebHID permission edge cases); mistakes could break reconnect or leak listeners, but behavior is heavily covered by new tests. > > **Overview** > Fixes Ledger DMK offscreen handling when **WebHID permission is revoked** (no native disconnect): cached bridges are **liveness-checked** against a snapshot of permitted `HIDDevice` objects, torn down synchronously when stale, and rebuilt without blocking on a hung `bridge.destroy()`. > > **Transport teardown** is new: each bridge’s WebHID transport is captured at creation and **`destroy()`** is invoked on disconnect, permission loss, `forceReset`, handler destroy, and failed/orphaned construction—so `navigator.hid` listeners do not leak in the long-lived offscreen document. Bridge construction state (transport + device snapshot) is only published after the generation check to avoid races with discarded in-flight builds. > > **RPC error messaging**: hardware-wallet `getErrorMessage` now uses `extractMessageFromUnknownError`, so plain-object failures are **JSON-stringified** instead of `"[object Object]"`. Tests cover stale-bridge, permission revoke/re-grant, transport lifecycle, and the updated discovery error message. > > <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit 7877570. Bugbot is set up for automated code reviews on this repo. Configure [here](https://www.cursor.com/dashboard/bugbot).</sup> <!-- /CURSOR_SUMMARY -->
<!-- CURSOR_AGENT_PR_BODY_BEGIN --> ## **Description** The remote flag `extension-ux-default-address-versioned` (`extensionUxDefaultAddressVersioned`) is already enabled in production. This change removes the client check and keeps the enabled behavior permanently. Default address stays available in settings, the account list, the QR sync account list, and the homepage header. The **Show default address** preference still controls whether the address is displayed. The registry entry is marked deprecated, with the production default unchanged, so the daily flag sync does not re-add it as an active flag before it is retired server-side. ## **Changelog** CHANGELOG entry: null ## **Related issues** Fixes: ## **Manual testing steps** 1. Run the extension and unlock or create a wallet. 2. On the homepage, confirm the default address is shown under the account name in the header. 3. Open the address popover from that header row and confirm the **Show default address** section is present. 4. Open Settings, then General (Preferences and display). 5. Confirm the **Show default address** toggle and network dropdown are visible. 6. Turn **Show default address** off. 7. Return to the homepage and confirm the default address is hidden in the header. 8. Open the account list and confirm account rows no longer show the default address. 9. Turn **Show default address** back on and confirm the address returns in the header and account list. <!-- ## **Screenshots/Recordings** ### **Before** ### **After** --> ## **Pre-merge author checklist** - [ ] I've followed [MetaMask Contributor Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Extension Coding Standards](https://github.com/MetaMask/metamask-extension/blob/main/.github/guidelines/CODING_GUIDELINES.md). - [ ] I've completed the PR template to the best of my ability - [ ] I’ve included tests if applicable - [ ] I’ve documented my code using [JSDoc](https://jsdoc.app/) format if applicable - [ ] I’ve applied the right labels on the PR (see [labeling guidelines](https://github.com/MetaMask/metamask-extension/blob/main/.github/guidelines/LABELING_GUIDELINES.md)). Not required for external contributors. ## **Pre-merge reviewer checklist** - [ ] I've manually tested the PR (e.g. pull and build branch, run the app, test code being changed). - [ ] I confirm that this PR addresses all acceptance criteria described in the ticket it closes and includes the necessary testing evidence such as recordings and or screenshots. <!-- CURSOR_AGENT_PR_BODY_END --> <div><a href="https://cursor.com/agents/bc-e450b381-60f1-42c5-9e00-eabf31013f7f?cursor_ref=pr_footer&cursor_cta=open_in_web"><picture><source media="(prefers-color-scheme: dark)" srcset="https://cursor.com/assets/images/open-in-web-dark.png"><source media="(prefers-color-scheme: light)" srcset="https://cursor.com/assets/images/open-in-web-light.png"><img alt="Open in Web" width="114" height="28" src="https://cursor.com/assets/images/open-in-web-dark.png"></picture></a> <a href="https://cursor.com/background-agent?bcId=bc-e450b381-60f1-42c5-9e00-eabf31013f7f&cursor_ref=pr_footer&cursor_cta=open_in_cursor"><picture><source media="(prefers-color-scheme: dark)" srcset="https://cursor.com/assets/images/open-in-cursor-dark.png"><source media="(prefers-color-scheme: light)" srcset="https://cursor.com/assets/images/open-in-cursor-light.png"><img alt="Open in Cursor" width="131" height="28" src="https://cursor.com/assets/images/open-in-cursor-dark.png"></picture></a> </div> --------- Co-authored-by: Cursor Agent <cursoragent@cursor.com> Co-authored-by: Amélie <ameliejyc@users.noreply.github.com>
<!-- Please submit this PR as a draft initially. Do not mark it as "Ready for review" until the template has been completely filled out, and PR status checks have passed at least once. --> ## **Description** <details> <summary>Tron release changelog v4.0.0</summary> ### Added - Add `signProofOfOwnershipBatch` for signing multiple proof-of-ownership messages in one request. ([#265](MetaMask/internal-snaps#265)) - Emit `Transaction Added`, `Transaction Approved`, and `Transaction Rejected` for `signTransaction` confirmations ([#333](MetaMask/internal-snaps#333)) - Only dApp-initiated transaction confirmations were affected; the unified send flow already emitted these events. - Report account synchronization failures to Sentry with the failing account IDs and their failure reasons ([#374](MetaMask/internal-snaps#374)) ### Changed - **BREAKING** Bump `@metamask/keyring-api` from `^23.7.0` to `^24.1.0` ([#214](MetaMask/internal-snaps#214)) - **BREAKING** Bump `@metamask/keyring-snap-sdk` from `^9.2.1` to `^10.0.0` ([#214](MetaMask/internal-snaps#214)) - **BREAKING** Bump `@metamask/snaps-sdk` from `^11.2.0` to `^12.0.1` ([#214](MetaMask/internal-snaps#214)) ### Removed - **BREAKING** Remove the deprecated `asset` cluster of handlers: `onAssetHistoricalPrice`, `onAssetsConversion`, `onAssetsLookup` and `onAssetsMarketData` ([#263](MetaMask/internal-snaps#263)) ### Fixed - Emit `Transaction Submitted` from the Wallet Standard `signAndSendTransaction` path so its transactions no longer reach `Transaction Finalized` without a matching submit event ([#343](MetaMask/internal-snaps#343)) - Tolerate unknown fields in the Token API metadata response so that new fields added by the API no longer fail validation and fall back to default token metadata ([#320](MetaMask/internal-snaps#320)) </details> <details> <summary>Solana release changelog v7.0.0</summary> ### Added - Add `signProofOfOwnershipBatch` for signing multiple proof-of-ownership messages in one request. ([#256](MetaMask/internal-snaps#256)) - Add back the `endowment:assets` permission for the Solana scopes to the snap manifest, with no-op `onAssetsLookup`, `onAssetsConversion`, `onAssetHistoricalPrice`, and `onAssetsMarketData` entry points required to keep the permission ([#274](MetaMask/internal-snaps#274)) - Report account synchronization failures to Sentry with the failing account IDs and their failure reasons ([#376](MetaMask/internal-snaps#376)) ### Changed - **BREAKING:** Bump `@solana/kit` from `^6.9.0` to `^8.3.0` and the `@solana-program/*` clients (`compute-budget` `^0.18.1`, `system` `^0.14.1`, `token` `^0.16.1`, `token-2022` `^0.17.0`) to their Kit 8-compatible versions. ([#303](MetaMask/internal-snaps#303)) - **BREAKING:** Update the Solana Name Service integration to SNS SDK v1 and the Kit 6.9-compatible Solana program clients ([#271](MetaMask/internal-snaps#271)) - **BREAKING** Bump `@metamask/keyring-api` from `^23.7.0` to `^24.1.0` ([#214](MetaMask/internal-snaps#214)) - **BREAKING** Bump `@metamask/keyring-snap-sdk` from `^9.2.1` to `^10.0.0` ([#214](MetaMask/internal-snaps#214)) - **BREAKING** Bump `@metamask/snaps-sdk` from `^11.2.0` to `^12.0.1` ([#214](MetaMask/internal-snaps#214)) - Reduce `snap_getBip32Entropy` calls in `createAccounts` from two to one for `bip44:discover` by deriving the activity-check address locally from the already-fetched coin-type node, and parallelize the entropy fetch with the existing-accounts state read for all creation paths ([#304](MetaMask/internal-snaps#304)) - Coalesce concurrent `AccountsSynchronizer.synchronize` calls for the same account set so duplicate in-flight syncs (e.g. simultaneous connection-recovery events across mainnet and devnet) share one run instead of fanning out redundant asset and transaction fetches ([#304](MetaMask/internal-snaps#304)) - Migrate `trackError` and `withCatchAndThrowSnapError` to `@metamask/snap-networks-utils` `createSnapErrorHandling`, and add `getSnapProvider` for Snap RPC access - Extract Snap-owned assets domain logic into `SnapAssetsAdapter`; `AssetsService` is a thin facade that delegates metadata, market data, fetch, persist, and account asset reads through the adapter (no Core routing yet). ([#121](MetaMask/internal-snaps#121)) - Align `AssetsService` read API with `snap-networks-utils` / AssetsController shapes by adding `getAccountAssetByID`, `getAccountAssetsByIDs`, `getAccountAssetsByScope`, and `getAccountAssets`, and routing Keyring and Send through them (still Snap-owned storage). ([#120](MetaMask/internal-snaps#120)) - Bump `@metamask/utils` from `^11.9.0` to `^11.11.9` ([#161](MetaMask/internal-snaps#161)) ### Removed - **BREAKING** Remove the `onAssetsLookup`, `onAssetsConversion`, `onAssetHistoricalPrice`, and `onAssetsMarketData` asset handler entry points, along with the now-unused handler modules and the `endowment:assets` permission ([#261](MetaMask/internal-snaps#261)) - **BREAKING** Remove `AssetsService.fetchAssetsMarketData` and `SnapAssetsAdapter.fetchAssetsMarketData`, the `TokenPricesService` class, and `PriceApiClient.getHistoricalPrices`, all of which were only used by the removed asset handlers ([#261](MetaMask/internal-snaps#261)) - Remove the now-unused `PriceApiClient.getFiatExchangeRates` method and related `ExchangeRate` type, the unused `tokenPrices` unencrypted state field, the unused `fiatExchangeRates` and `historicalPrices` price API cache TTL options, and unused price API test mocks ([#261](MetaMask/internal-snaps#261)) ### Fixed - **BREAKING:** Preserve dapp-origin `signTransaction` and `signAndSendTransaction` payloads by signing the decoded transaction directly ([#156](MetaMask/internal-snaps#156)) - Prevent signing dapp transactions with expired blockhashes, and refresh the blockhash for MetaMask-originated transactions before signing. ([#183](MetaMask/internal-snaps#183)) - Tolerate unknown fields in the Price API spot price and Token API metadata responses so that new fields added by the API no longer fail validation ([#321](MetaMask/internal-snaps#321)) - Emit an `AccountTransactionsUpdated` keyring event with a pending `unconfirmed` transaction immediately after broadcasting. </details> <details> <summary>Bitcoin release changelog v3.1.0</summary> ### Added - Add `signProofOfOwnershipBatch` for signing multiple proof-of-ownership messages in one request. ([#266](MetaMask/internal-snaps#266)) - Emit `Transaction Added`, `Transaction Approved`, and `Transaction Rejected` tracking events from Bitcoin transaction confirmations ([#328](MetaMask/internal-snaps#328), [#329](MetaMask/internal-snaps#329)) - Report account synchronization failures to Sentry with the failing account IDs and their failure reasons ([#375](MetaMask/internal-snaps#375)) ### Fixed - Populate the `from` address of receive transactions by resolving the addresses that funded them through the chain indexer. Bitcoin inputs only reference a previous outpoint, so the sender was previously left empty. ([#372](MetaMask/internal-snaps#372)) </details> <!-- Write a short description of the changes included in this pull request, also include relevant motivation and context. Have in mind the following questions: 1. What is the reason for the change? 2. What is the improvement/solution? --> ## **Changelog** <!-- If this PR is not End-User-Facing and should not show up in the CHANGELOG, you can choose to either: 1. Write `CHANGELOG entry: null` 2. Label with `no-changelog` If this PR is End-User-Facing, please write a short User-Facing description in the past tense like: `CHANGELOG entry: Added a new tab for users to see their NFTs` `CHANGELOG entry: Fixed a bug that was causing some NFTs to flicker` (This helps the Release Engineer do their job more quickly and accurately) --> CHANGELOG entry: null ## **Related issues** n/a ## **Manual testing steps** n/a ## **Screenshots/Recordings** <!-- If applicable, add screenshots and/or recordings to visualize the before and after of your change. --> ### **Before** <!-- [screenshots/recordings] --> n/a ### **After** <!-- [screenshots/recordings] --> n/a ## **Pre-merge author checklist** - [ ] I've followed [MetaMask Contributor Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Extension Coding Standards](https://github.com/MetaMask/metamask-extension/blob/main/.github/guidelines/CODING_GUIDELINES.md). - [ ] I've completed the PR template to the best of my ability - [ ] I’ve included tests if applicable - [ ] I’ve documented my code using [JSDoc](https://jsdoc.app/) format if applicable - [ ] I’ve applied the right labels on the PR (see [labeling guidelines](https://github.com/MetaMask/metamask-extension/blob/main/.github/guidelines/LABELING_GUIDELINES.md)). Not required for external contributors. ## **Pre-merge reviewer checklist** - [ ] I've manually tested the PR (e.g. pull and build branch, run the app, test code being changed). - [ ] I confirm that this PR addresses all acceptance criteria described in the ticket it closes and includes the necessary testing evidence such as recordings and or screenshots. <!-- CURSOR_SUMMARY --> --- > [!NOTE] > **Medium Risk** > Major Solana and Tron snap upgrades can change signing, sync, and keyring behavior in production multichain flows; extension code changes are limited to dependency versions and e2e mocks. > > **Overview** > Bumps bundled multichain wallet Snaps: **Solana** `5.0.1` → `7.0.0`, **Tron** `3.2.0` → `4.0.0`, and **Bitcoin** `3.0.0` → `3.1.0`, with matching `yarn.lock` updates. > > E2E tests are adjusted for the new Solana snap behavior: the multichain `wallet_invokeMethod` **signAndSendTransaction** assertion uses an updated expected transaction **signature**, and the SPL token send success mocks swap **`mockGetTokenAccountBalance`** for **`mockGetSuccessSignaturesForAddress`** after broadcast so activity/history RPC expectations align with v7. > > <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit c3efb9d. Bugbot is set up for automated code reviews on this repo. Configure [here](https://www.cursor.com/dashboard/bugbot).</sup> <!-- /CURSOR_SUMMARY -->
## **Description** Part 8 of the 18-part assets-unification stack. test(assets): cover unified multichain and currency selectors. This focused slice keeps the review below the 1,000 changed-line limit while preserving the final behavior of the original PR. ## **Changelog** CHANGELOG entry: null <!-- ## **Related issues** Fixes: --> ## **Manual testing steps** 1. Build and load the extension. 2. Unlock or onboard a wallet. 3. Verify home balances and token lists render. 4. Open send and bridge token selectors and verify assets are available. <!-- ## **Screenshots/Recordings** ### **Before** ### **After** --> ## **Pre-merge author checklist** - [x] I have followed MetaMask coding standards. - [x] I have completed the PR template. - [x] I have included tests where applicable. ## **Pre-merge reviewer checklist** - [ ] I have manually tested the PR. - [ ] I confirm the acceptance criteria and testing evidence. <!-- CURSOR_SUMMARY --> --- > [!NOTE] > **Low Risk** > Test-only refactor in assets-migration.test.ts; no production selector logic changes in this diff. > > **Overview** > Refactors **`assets-migration.test.ts`** so multichain and currency migration selectors are exercised only on the **assets-unify enabled** path, matching the stack’s expected runtime behavior. > > For `getMultiChainAssetsControllerAssetsMetadata`, `getMultiChainAssetsControllerAllIgnoredAssets`, `getMultiChainBalancesControllerBalances`, `getCurrencyRateControllerCurrentCurrency`, `getCurrencyRateControllerCurrencyRates`, and `getTokenRatesControllerMarketData`, it **drops** nested “feature disabled / legacy passthrough” suites and **flattens** the enabled cases: shared `enabledFlags` fixtures, top-level happy-path `it`s, and `edge cases` blocks without the “when enabled” wrapper. Assertions for unified derivation (non-EVM filtering, Tempo USD rates, native-currency market data) are unchanged. > > <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit f5fe123. Bugbot is set up for automated code reviews on this repo. Configure [here](https://www.cursor.com/dashboard/bugbot).</sup> <!-- /CURSOR_SUMMARY --> --------- Co-authored-by: Cursor <cursoragent@cursor.com>
…46859) ## **Description** The add-network form had a separate **Add from Chainlist** button that opened another screen. [CEUX-1312](https://consensyssoftware.atlassian.net/browse/CEUX-1312) asks for Chainlist suggestions on the form itself. Clicking or focusing the **Network name** field now opens the Chainlist list under that field. Typing filters by network name or chain ID. Choosing a suggestion prefills the form (name, chain ID, symbol, RPC URL, and block explorer) and uses the existing add flow. An already-added chain still opens the edit screen. Typing a name without picking a suggestion leaves the other fields unchanged. The **Add from Chainlist** button is removed. The old `?view=add-from-chainlist` screen is still reachable by URL. Chain ID does not open the same suggestions yet. ## **Changelog** CHANGELOG entry: Added Chainlist suggestions to the network name field when adding a network ## **Related issues** Related: [CEUX-1312](https://consensyssoftware.atlassian.net/browse/CEUX-1312) ## **Manual testing steps** 1. Run the extension and set the flag (`extension-ux-chainlist-v-2`) to true 2. Open Settings → Networks → Add a custom network. 3. Confirm there is no **Add from Chainlist** button. 4. Click **Network name**. Confirm the Chainlist banner and network list open under the field. 5. Type part of a network name or a chain ID and confirm the list filters. An empty field shows the full list. 6. Select a network that is not already added. Confirm name, chain ID, symbol, RPC URL, and block explorer are filled, then save. 7. Select a network that is already added. Confirm the edit-network screen opens for that chain. 8. Type a custom name, click outside the list, and fill the other fields by hand. Confirm they are not overwritten. 9. Edit an existing network. Confirm the suggestions do not open and Chain ID stays disabled. ## **Screenshots/Recordings** ### **Before** NA ### **After** https://github.com/user-attachments/assets/32e0584e-afa7-4fe6-8acc-3061134dfc24 ## **Pre-merge author checklist** - [x] I've followed [MetaMask Contributor Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Extension Coding Standards](https://github.com/MetaMask/metamask-extension/blob/main/.github/guidelines/CODING_GUIDELINES.md). - [x] I've completed the PR template to the best of my ability - [x] I’ve included tests if applicable - [ ] I’ve documented my code using [JSDoc](https://jsdoc.app/) format if applicable - [x] I’ve applied the right labels on the PR (see [labeling guidelines](https://github.com/MetaMask/metamask-extension/blob/main/.github/guidelines/LABELING_GUIDELINES.md)). Not required for external contributors. ## **Pre-merge reviewer checklist** - [ ] I've manually tested the PR (e.g. pull and build branch, run the app, test code being changed). - [ ] I confirm that this PR addresses all acceptance criteria described in the ticket it closes and includes the necessary testing evidence such as recordings and or screenshots. Made with [Cursor](https://cursor.com) [CEUX-1312]: https://consensyssoftware.atlassian.net/browse/CEUX-1312?atlOrigin=eyJpIjoiNWRkNTljNzYxNjVmNDY3MDlhMDU5Y2ZhYzA5YTRkZjUiLCJwIjoiZ2l0aHViLWNvbS1KU1cifQ [CEUX-1312]: https://consensyssoftware.atlassian.net/browse/CEUX-1312?atlOrigin=eyJpIjoiNWRkNTljNzYxNjVmNDY3MDlhMDU5Y2ZhYzA5YTRkZjUiLCJwIjoiZ2l0aHViLWNvbS1KU1cifQ --------- Co-authored-by: Cursor <cursoragent@cursor.com>
…46777) <!-- Please submit this PR as a draft initially. Do not mark it as "Ready for review" until the template has been completely filled out, and PR status checks have passed at least once. --> ## **Description** Bump @metamask/delegation-deployments from ^2.0.0 to ^2.1.0, bringing Ark chain deployments. ## **Changelog** <!-- If this PR is not End-User-Facing and should not show up in the CHANGELOG, you can choose to either: 1. Write `CHANGELOG entry: null` 2. Label with `no-changelog` If this PR is End-User-Facing, please write a short User-Facing description in the past tense like: `CHANGELOG entry: Added a new tab for users to see their NFTs` `CHANGELOG entry: Fixed a bug that was causing some NFTs to flicker` (This helps the Release Engineer do their job more quickly and accurately) --> CHANGELOG entry: @metamask/delegation-deployments from ^2.0.0 to ^2.1.0 ## **Related issues** Fixes: ## **Manual testing steps** 1. Go to this page... 2. 3. ## **Screenshots/Recordings** <!-- If applicable, add screenshots and/or recordings to visualize the before and after of your change. --> ### **Before** <!-- [screenshots/recordings] --> ### **After** <!-- [screenshots/recordings] --> ## **Pre-merge author checklist** - [ ] I've followed [MetaMask Contributor Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Extension Coding Standards](https://github.com/MetaMask/metamask-extension/blob/main/.github/guidelines/CODING_GUIDELINES.md). - [ ] I've completed the PR template to the best of my ability - [ ] I’ve included tests if applicable - [ ] I’ve documented my code using [JSDoc](https://jsdoc.app/) format if applicable - [ ] I’ve applied the right labels on the PR (see [labeling guidelines](https://github.com/MetaMask/metamask-extension/blob/main/.github/guidelines/LABELING_GUIDELINES.md)). Not required for external contributors. ## **Pre-merge reviewer checklist** - [ ] I've manually tested the PR (e.g. pull and build branch, run the app, test code being changed). - [ ] I confirm that this PR addresses all acceptance criteria described in the ticket it closes and includes the necessary testing evidence such as recordings and or screenshots. <!-- CURSOR_SUMMARY --> --- > [!NOTE] > **Low Risk** > Lockfile-only bump of deployment metadata; no local logic changes, though wrong addresses on a new chain would affect delegation flows on Ark. > > **Overview** > Updates **`@metamask/delegation-deployments`** from **^2.0.0** to **^2.1.0** in `package.json`, with the matching **`yarn.lock`** resolution for **2.1.0**. > > Per the PR description, **2.1.0** adds **Ark chain** delegator deployment metadata consumed transitively by delegation-related controllers (e.g. `@metamask/delegation-controller`, gator permissions, money-account upgrade). There are **no extension source changes** in this diff—only the dependency version. > > <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit 3e19080. Bugbot is set up for automated code reviews on this repo. Configure [here](https://www.cursor.com/dashboard/bugbot).</sup> <!-- /CURSOR_SUMMARY -->
<!-- Please submit this PR as a draft initially. Do not mark it as "Ready for review" until the template has been completely filled out, and PR status checks have passed at least once. --> ## **Description** Stabilize the phishing detection E2E that times out on Firefox while the warning is already showing inside an iframe. **Flake type:** Race Conditions with Windows **Root cause:** - The test opens a mock page that puts a blocked site inside an iframe. - Early blocking is turned off, so the iframe loads the blocked site first. - A content script then moves that frame to the MetaMask phishing warning. - The helper finds the first iframe and switches into it once, about half a second after the page opens. - The frame is often still the blocked site at that moment. - It then waits for the heading "This website might be harmful". - On Firefox, that one-time switch stays on a frame that never gets the heading, even after the warning is painted. - The failed page already shows the warning inside the iframe while the test times out. - The helper only goes back to the top page after that wait, which is too late. **Solution:** - Return to the top page and enter the iframe again until the warning heading is visible, so the click runs in the frame that actually shows the warning. - Click "Open this warning in a new tab" once after that wait, so an early switch is not treated as a click to retry. Slack: https://consensys.slack.com/archives/CTQAGKY5V/p1790848005313319?thread_ts=1790843210.528129&cid=CTQAGKY5V ## **Changelog** CHANGELOG entry: null <!-- ## **Related issues** Fixes: --> ## **Manual testing steps** 1. Start a test build with `yarn start:test`. This spec is not a Flask test. 2. Remove `it.only` from the failing test before committing or opening a PR. 3. Run: ```bash SELENIUM_BROWSER=chrome yarn test:e2e:single test/e2e/tests/phishing-controller/phishing-detection.spec.ts --debug --leave-running ``` This race shows up on Firefox. Chrome usually passes. To hit the same failure, use a Firefox test build (`yarn start:test:mv2`) and set `SELENIUM_BROWSER=firefox` on that command. ## **Screenshots/Recordings** <img width="1366" height="682" alt="image" src="https://github.com/user-attachments/assets/bf135dc9-bafd-40e2-aa66-ef8fe3b741ac" /> ### **Before** CI failure screenshot: a mock page with "Hello" at the top left and a large black iframe that already shows the MetaMask phishing warning ("This website might be harmful", warning icon, and the link "Open this warning in a new tab"). The test still timed out looking for that heading inside the iframe. A second screenshot is the MetaMask home window left open after login (Account 1, 25 ETH, Network: Localhost 8545). The test never returned to that window because the iframe wait failed first. ### **After** No product UI change. The helper returns to the top page, re-enters the iframe until the warning heading is visible, then clicks "Open this warning in a new tab" once. ## **Pre-merge author checklist** - [ ] I've followed [MetaMask Contributor Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Extension Coding Standards](https://github.com/MetaMask/metamask-extension/blob/main/.github/guidelines/CODING_GUIDELINES.md). - [ ] I've completed the PR template to the best of my ability - [ ] I’ve included tests if applicable - [ ] I’ve documented my code using [JSDoc](https://jsdoc.app/) format if applicable - [ ] I’ve applied the right labels on the PR (see [labeling guidelines](https://github.com/MetaMask/metamask-extension/blob/main/.github/guidelines/LABELING_GUIDELINES.md)). Not required for external contributors. ## **Pre-merge reviewer checklist** - [ ] I've manually tested the PR (e.g. pull and build branch, run the app, test code being changed). - [ ] I confirm that this PR addresses all acceptance criteria described in the ticket it closes and includes the necessary testing evidence such as recordings and or screenshots. <!-- CURSOR_SUMMARY --> --- > [!NOTE] > **Low Risk** > Test-only page-object change; no product or runtime behavior. > > **Overview** > Fixes a **Firefox flake** in the phishing-detection E2E where the helper switched into an iframe once while it still showed the blocked site, then timed out waiting for the warning heading even after the interstitial appeared. > > **`clickOpenWarningInNewTabLinkOnIframe`** now **polls** (up to 10s): reset to default content, re-find the iframe, switch in, and confirm **"This website might be harmful"** is visible before clicking **"Open this warning in a new tab"** once. Drops the unused **`WebElement`** import and the old one-shot frame switch plus **`checkPageIsLoaded`** path. > > <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit f77e4a4. Bugbot is set up for automated code reviews on this repo. Configure [here](https://www.cursor.com/dashboard/bugbot).</sup> <!-- /CURSOR_SUMMARY --> --------- Co-authored-by: Cursor <cursoragent@cursor.com>
There was a problem hiding this comment.
Stale comment
Modern web & extension review (actionable)
Reviewed client-facing changes under
ui//shared/and extension work underapp/against modern-web-guidance and chrome-extensions patterns.Cashtag (X) widget — browser support gaps
Interest Invokers have no fallback.
bindWidgetTriggersopens the widget only viainterestforon cashtag anchors. Elsewhere in the extension (e.g.ui/pages/ramps/payment-method/components/ramps-quote-display.tsx) we feature-detectinterestForand ship a pointer/focus fallback. Without the same pattern, the widget will not open on browsers that lack Interest Invokers (including Firefox and older Chromium builds).Invoker Commands are used without a polyfill or fallback.
OverflowMenuandDisableConfirmDialogdepend oncommand/commandfor(toggle-popover,show-modal,close). modern-web-guidance calls for feature detection and the invokers polyfill when native support is missing; there is no polyfill in this repo today, so disable/menu flows can be inert outside supporting browsers.Content script DOM work should be batched.
injectPills/bindWidgetTriggerspaint cashtags synchronously inside aMutationObserverloop. chrome-extensions guidance recommends batching DOM updates withrequestAnimationFrame(and yielding on long feeds) to avoid main-thread jank on X timelines.Accessibility
PriceChartis a canvas with no accessible name or text alternative. Add at leastaria-label/role="img"with a concise price summary, or expose a screen-reader-friendly value table per accessibility guidance for charts.Minor
OverflowMenuacceptsariaLabel/testIdbut always hard-codes the trigger label — wire the props through or drop them from the public API.Other UI changes in this release (tabs keyboard handling, labeled RPC form fields, native
<dialog>for disable confirm) align well with modern patterns where supported.Sent by Cursor Automation: Modern web guidance
| if (mounted.has(element)) { | ||
| return; | ||
| } | ||
| element.setAttribute('interestfor', popoverId); |
There was a problem hiding this comment.
Widget open is tied exclusively to interestfor. Consider mirroring interestInvokerSupport + fallback handlers from ramps-quote-display.tsx (click/focus + popover show/hide) so cashtags work when Interest Invokers are unavailable.
| ariaLabel="More options" | ||
| style={{ anchorName: '--menu-trigger' } as React.CSSProperties} | ||
| // @ts-expect-error need to update react types | ||
| command="toggle-popover" |
There was a problem hiding this comment.
Invoker Commands (toggle-popover / item show-modal) need a feature-detect + invokers-polyfill (or explicit click handlers) per modern-web-guidance — otherwise this menu is a no-op on unsupported browsers, including inside the X iframe widget.
| ); | ||
| } | ||
|
|
||
| return <div ref={containerRef} className="h-[170px] w-full" />; |
There was a problem hiding this comment.
Chart container is a bare <div> around a canvas with no accessible name. Please add an aria-label / role="img" with a short price summary, or an sr-only text alternative for the series.
|
|
||
| scan(document); | ||
|
|
||
| const observer = new MutationObserver((mutations) => { |
There was a problem hiding this comment.
This observer can call paint/replaceChildren for many nodes in one turn. Batch scans/paints with requestAnimationFrame (and yield between batches on large feeds) to match content-script performance guidance and reduce INP risk on X.
Builds ready [a13345c]
⚡ Performance Benchmarks (Total: 🟢 8 pass · 🟡 2 warn · 🔴 3 fail)
Bundle Size Diffs [🚨 Warning! Bundle size has increased!]
Cherry-picks (9 commits)
Changelog (51 commits since v13.52.0)
AI Test Plan
Cherry-Pick Scenarios (2)High Risk Scenarios (1)1. QR Hardware Wallet - Send Flow UnblockedRisk Level: HIGH Why This Matters: Cherry-pick 47088 fixes an infinite loading issue in the QR signing flow; a regression here blocks users from sending funds with QR hardware wallets. Test Steps:
Medium Risk Scenarios (1)1. QR Hardware Wallet - Error Handling and RetryRisk Level: MEDIUM Why This Matters: Cherry-pick 47088 fixes stuck states; validating error and retry paths ensures users can recover without re-importing or creating duplicate sends. Test Steps:
Release Scenarios (10)High Risk Scenarios (4)1. Hardware Wallet (Ledger) - Transaction Signing and SendRisk Level: HIGH Why This Matters: Large refactor in the Ledger offscreen handler can break connection lifecycle and signing flows, impacting users who rely on hardware wallets for security-critical transactions. Test Steps:
2. Transaction Flow - Transaction Pay Controller IntegrationRisk Level: HIGH Why This Matters: New controller initialization in the transaction pipeline can cause regressions in submission, replacement (speed up), and cancellation handling. Test Steps:
3. Transaction/Signature Restore After Extension ReloadRisk Level: HIGH Why This Matters: Changes in messenger-client init and controller wiring can break pending approval restoration, causing stuck dapp flows and loss of user actions. Test Steps:
4. Multichain Accounts - Default Address Indicator and CopyRisk Level: HIGH Why This Matters: Hook and preferences changes can desync the default address state, confusing users and risking mis-sends. Test Steps:
Medium Risk Scenarios (6)1. Security Trust Inline Badge - Visibility and DetailsRisk Level: MEDIUM Why This Matters: UI logic changes can misrepresent trust levels or obstruct core actions on critical approval screens. Test Steps:
2. Token List - Search, Hide/Unhide, Network SwitchingRisk Level: MEDIUM Why This Matters: Token list changes risk incorrect filtering, state sync, and visibility toggles—leading to user confusion or missing assets. Test Steps:
3. Coin Overview - Quick Actions (Buy/Swap/Send/Receive)Risk Level: MEDIUM Why This Matters: Changes to the coin overview can break entry points to core flows (buy/swap/send/receive) and cause mis-estimates or wrong addresses. Test Steps:
4. Account Overview Layout - Navigation and ResponsivenessRisk Level: MEDIUM Why This Matters: Layout updates can introduce visual regressions that hide actions or mislead users about balances and activity. Test Steps:
5. Hardware Wallet (Ledger) - Offscreen Recovery and ReconnectionRisk Level: MEDIUM Why This Matters: Offscreen handling changes can cause connection drops or stuck states when the extension is backgrounded or the OS sleeps. Test Steps:
6. Assets Persistence Across UpgradeRisk Level: MEDIUM Why This Matters: Subtle state/migration or selector changes can cause missing or duplicated assets after an upgrade. Test Steps:
Teams Sign-off StatusSigned off: None yet Awaiting sign-off (8): Generated by AI Test Plan Analyzer (gpt-5) at 2026-10-19T18:37:55.433Z AI generated test plan (JSON): test-plan-13.53.0.json |
There was a problem hiding this comment.
Modern web / Chrome extension review
Reviewed client-facing changes under ui//shared/ and extension work under app/ (especially the new X cashtag content script + widget). Most of the new UI follows current patterns well (native <dialog>/Popover, invoker commands, anchor positioning, frame-ancestors for the embedded widget).
Actionable items below are limited to the X timeline injection path, where main-thread cost and Baseline gaps are most likely to show up in production.
Sent by Cursor Automation: Modern web guidance
|
|
||
| scan(document); | ||
|
|
||
| const observer = new MutationObserver((mutations) => { |
There was a problem hiding this comment.
Chrome extension content-script perf: This MutationObserver runs scan() synchronously for every added subtree. On X’s infinite-scroll feed that can mean large querySelectorAll + per-anchor replaceChildren() work inside a single observer callback, blocking the page main thread.
Please batch visual DOM work (e.g. collect anchors first, then paint in chunks via requestAnimationFrame, yielding with scheduler.yield() when available), matching the content-script guidance for heavy DOM updates.
|
|
||
| scan(document); | ||
|
|
||
| const observer = new MutationObserver((mutations) => { |
There was a problem hiding this comment.
Same main-thread concern as pill injection: the observer here can run scan()/prune() synchronously across big DOM subtrees as tweets stream in. Consider deferring scan work to idle/rAF batches so hover/scroll on X stays responsive.
| if (mounted.has(element)) { | ||
| return; | ||
| } | ||
| element.setAttribute('interestfor', popoverId); |
There was a problem hiding this comment.
Modern web Baseline / fallback: Widget open/hover is wired through interestfor + :interest-source with no feature detection or fallback. This release already adds an explicit Interest Invoker capability check + fallback path in ui/pages/ramps/payment-method/components/ramps-quote-display.tsx.
Without a similar guard (polyfill or click/focus fallback), browsers without native Interest Invokers get pills but no popover/widget. Recommend detecting 'interestFor' in HTMLAnchorElement.prototype (or equivalent) and providing a degraded open path before rollout.


🚀 v13.53.0 Testing & Release Quality Process
Hi Team,
As part of our new MetaMask Release Quality Process, here’s a quick overview of the key processes, testing strategies, and milestones to ensure a smooth and high-quality deployment.
📋 Key Processes
Testing Strategy
Conduct regression and exploratory testing for your functional areas, including automated and manual tests for critical workflows.
Focus on exploratory testing across the wallet, prioritize high-impact areas, and triage any Sentry errors found during testing.
Validate new functionalities and provide feedback to support release monitoring.
GitHub Signoff
Issue Resolution
Cherry-Picking Criteria
🗓️ Timeline and Milestones
✅ Signoff Checklist
Each team is responsible for signing off via GitHub. Use the checkbox below to track signoff completion:
Team sign-off checklist
This process is a major step forward in ensuring release stability and quality. Let’s stay aligned and make this release a success! 🚀
Feel free to reach out if you have questions or need clarification.
Many thanks in advance
Reference